@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/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: config.tenantTables?.length ?? 0,
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)) return void 0;
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") return "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") return "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)) return void 0;
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"]) return { name: "next", version: deps["next"] };
78
- if (deps["hono"]) return { name: "hono", version: deps["hono"] };
79
- if (deps["express"]) return { name: "express", version: deps["express"] };
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)) return void 0;
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
- if (deps["prisma"]) return { name: "prisma", version: deps["prisma"] };
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") return void 0;
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")) return { name: "pnpm" };
122
- if (ua.includes("yarn")) return { name: "yarn" };
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") return false;
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") return false;
129
- if (env === "1" || env?.toLowerCase() === "true") return true;
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") return true;
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
- if (options?.loadTenant && options.getTenantRepository && adapter.runAsSystem) {
270
+ const getTenantRepository = options?.getTenantRepository;
271
+ if (options?.loadTenant && getTenantRepository && adapter.runAsSystem) {
237
272
  const tenant = await adapter.runAsSystem(
238
- (systemDb) => options.getTenantRepository(systemDb).getById(tenantId)
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) return 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) return void 0;
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) return void 0;
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) return void 0;
447
+ if (!host) {
448
+ return void 0;
449
+ }
410
450
  const hostname = host.split(":")[0];
411
- if (!hostname) return void 0;
451
+ if (!hostname) {
452
+ return void 0;
453
+ }
412
454
  const parts = hostname.split(".");
413
- if (parts.length <= 2) return void 0;
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) return null;
465
+ if (parts.length < 2) {
466
+ return null;
467
+ }
422
468
  const payload = parts[1];
423
- if (!payload) return null;
469
+ if (!payload) {
470
+ return null;
471
+ }
424
472
  const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
425
- return JSON.parse(decoded);
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) return void 0;
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) return void 0;
490
+ if (!resolved) {
491
+ return void 0;
492
+ }
437
493
  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;
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) return void 0;
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) return void 0;
522
+ if (!resolved) {
523
+ return void 0;
524
+ }
451
525
  const claim = typeof config === "string" ? config : config.claim;
452
- if (!claim) return void 0;
453
- const payload = decodeJwtPayload(resolved);
454
- if (!payload) return void 0;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return v;
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) return void 0;
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) return {};
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) return void 0;
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(request.path ?? request.originalUrl ?? request.url);
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,