@usebetterdev/tenant-core 0.1.0
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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/adapter.d.ts +24 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/api.d.ts +33 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/better-tenant.d.ts +40 -0
- package/dist/better-tenant.d.ts.map +1 -0
- package/dist/context.d.ts +16 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/handle-request.d.ts +17 -0
- package/dist/handle-request.d.ts.map +1 -0
- package/dist/index.cjs +677 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +636 -0
- package/dist/index.js.map +1 -0
- package/dist/request.d.ts +12 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/resolver.d.ts +11 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/telemetry.d.ts +97 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 usebetter
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @better-tenant/core
|
|
2
|
+
|
|
3
|
+
Core library for request-scoped multi-tenancy with Postgres RLS. Provides tenant context (AsyncLocalStorage), resolver strategies, adapter contract, and tenant API. No database driver dependency — use with [@usebetterdev/tenant-drizzle](https://github.com/usebetter-dev/usebetter) or a custom adapter.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @better-tenant/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { betterTenant, getContext, getDatabase } from "@better-tenant/core";
|
|
15
|
+
import { drizzleAdapter } from "better-tenant/drizzle"; // or your adapter
|
|
16
|
+
|
|
17
|
+
const adapter = drizzleAdapter(db);
|
|
18
|
+
const tenant = betterTenant({
|
|
19
|
+
adapter,
|
|
20
|
+
tenantResolver: { header: "x-tenant-id" },
|
|
21
|
+
tenantTables: ["projects", "tasks"],
|
|
22
|
+
getTenantRepository: (database) => ({ create, update, list, delete }), // adapter provides this
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// In middleware: resolve tenantId (e.g. tenant.resolveTenant(request)), then:
|
|
26
|
+
await tenant.runWithTenantAndDatabase(tenantId, adapter, async () => {
|
|
27
|
+
await next();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// In handlers:
|
|
31
|
+
const context = tenant.getContext(); // { tenantId, tenant?, database? }
|
|
32
|
+
const database = tenant.getDatabase(); // tenant-scoped DB handle (use only this for tenant tables)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## API
|
|
36
|
+
|
|
37
|
+
| API | Description |
|
|
38
|
+
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
39
|
+
| `betterTenant(config)` | Create instance with adapter, resolver, optional `getTenantRepository`. |
|
|
40
|
+
| `getContext()` | Current `TenantContext \| undefined` (tenantId, tenant?, database?). |
|
|
41
|
+
| `getDatabase()` | Tenant-scoped database handle, or `undefined` outside request scope. Use only this for tenant-scoped tables. |
|
|
42
|
+
| `runWithTenant(tenantId, fn)` | Run `fn` with context only (no DB). For tests or when adapter not used. |
|
|
43
|
+
| `runWithTenantAndDatabase(tenantId, adapter, fn)` | Set context and run `fn` with adapter’s tenant-scoped DB. Call from middleware. |
|
|
44
|
+
| `resolveTenant(request, config)` / `resolveTenantAsync` | Resolve tenant id from request (header, path, subdomain, jwt, custom). |
|
|
45
|
+
| `runAs(tenantId, adapter, fn)` | Same as request flow; use for cron or per-tenant jobs. |
|
|
46
|
+
| `runAsSystem(fn)` | Run with RLS bypass (adapter must implement `runAsSystem`). |
|
|
47
|
+
| `tenant.api` | `createTenant`, `updateTenant`, `listTenants`, `deleteTenant` (when `getTenantRepository` is set). |
|
|
48
|
+
|
|
49
|
+
## Adapter contract
|
|
50
|
+
|
|
51
|
+
Adapters implement `TenantAdapter`:
|
|
52
|
+
|
|
53
|
+
- **runWithTenant(tenantId, fn)** — Begin transaction → `SET LOCAL app.current_tenant = '<uuid>'` → call `fn(database)` → commit. Core does not run SQL.
|
|
54
|
+
- **runAsSystem?(fn)** — Optional; run `fn` with a DB handle that has RLS bypass (e.g. `SET LOCAL app.bypass_rls = true`).
|
|
55
|
+
|
|
56
|
+
Types: `TenantScopedDatabase` (opaque handle), `SystemDatabase` (opaque handle for system operations).
|
|
57
|
+
|
|
58
|
+
## Resolver
|
|
59
|
+
|
|
60
|
+
Resolution order: **header → path → subdomain → jwt → custom**. Configure `tenantResolver` with e.g. `header: "x-tenant-id"`, `path: "/t/:tenantId"`, `subdomain: true`, `jwt: { claim: "tenant_id" }`, or `custom: (req) => ...`.
|
|
61
|
+
|
|
62
|
+
## Telemetry
|
|
63
|
+
|
|
64
|
+
Anonymous telemetry is **on by default** to help improve the library. Data is sent to `https://telemetry.usebetter.dev` and includes runtime, framework, and redacted config (no PII or secrets). Telemetry is disabled in `NODE_ENV=test`.
|
|
65
|
+
|
|
66
|
+
**Opt out:** Set `telemetry: { enabled: false }` in your config or `BETTER_TENANT_TELEMETRY=0`.
|
|
67
|
+
|
|
68
|
+
**Debug mode:** Set `telemetry: { debug: true }` or `BETTER_TENANT_TELEMETRY_DEBUG=1` to log payloads to the console without sending.
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
- [Under the Hood](../docs/UNDER-THE-HOOD.md) — RLS, SET LOCAL, runAsSystem
|
|
73
|
+
- [Product plan](../docs/PLAN.md) — Roadmap, architecture
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TenantAdapter, TenantScopedDatabase, RunWithTenantAndDatabaseOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the tenant-scoped database handle when inside a runWithTenantAndDatabase (or runAs) scope.
|
|
4
|
+
*
|
|
5
|
+
* Use only the handle from getDatabase() for tenant-scoped tables. Outside scope, returns undefined.
|
|
6
|
+
* Config requires an adapter when tenant-scoped DB is used; getDatabase() is then available inside
|
|
7
|
+
* request handlers that ran via runWithTenantAndDatabase(tenantId, adapter, next).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDatabase(): TenantScopedDatabase | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Sets AsyncLocalStorage context and runs fn with the adapter's tenant-scoped DB.
|
|
12
|
+
*
|
|
13
|
+
* (1) Sets AsyncLocalStorage context with tenantId and database.
|
|
14
|
+
* (2) Calls adapter.runWithTenant(tenantId, (database) => fn(database)).
|
|
15
|
+
* (3) Stores the database handle in context so getDatabase() returns it.
|
|
16
|
+
*
|
|
17
|
+
* Middleware should resolve tenantId from the request, then call
|
|
18
|
+
* runWithTenantAndDatabase(tenantId, adapter, next) so both context and DB handle are available.
|
|
19
|
+
*
|
|
20
|
+
* When options.loadTenant is true and options.getTenantRepository and adapter.runAsSystem are set,
|
|
21
|
+
* loads the full Tenant row into context so getContext().tenant is available (or undefined if not found).
|
|
22
|
+
*/
|
|
23
|
+
export declare function runWithTenantAndDatabase<T>(tenantId: string, adapter: TenantAdapter, fn: (database: TenantScopedDatabase) => Promise<T>, options?: RunWithTenantAndDatabaseOptions): Promise<T>;
|
|
24
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAEb,oBAAoB,EACpB,+BAA+B,EAChC,MAAM,YAAY,CAAC;AAGpB;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,oBAAoB,GAAG,SAAS,CAG9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,EACtB,EAAE,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,OAAO,CAAC,CAAC,CAAC,EAClD,OAAO,CAAC,EAAE,+BAA+B,GACxC,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TenantAdapter, Tenant, SystemDatabase, TenantScopedDatabase, TenantRepository } from "./types.js";
|
|
2
|
+
export interface CreateTenantData {
|
|
3
|
+
name: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UpdateTenantData {
|
|
7
|
+
name?: string;
|
|
8
|
+
slug?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ListTenantsOptions {
|
|
11
|
+
limit?: number;
|
|
12
|
+
offset?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Tenant CRUD API. All methods run via adapter.runAsSystem and getTenantRepository.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createTenantApi(adapter: TenantAdapter, getTenantRepository: (database: SystemDatabase) => TenantRepository): {
|
|
18
|
+
createTenant(data: CreateTenantData): Promise<Tenant>;
|
|
19
|
+
updateTenant(tenantId: string, data: UpdateTenantData): Promise<Tenant>;
|
|
20
|
+
listTenants(options?: ListTenantsOptions): Promise<Tenant[]>;
|
|
21
|
+
deleteTenant(tenantId: string): Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* runAs(tenantId, fn): same as request flow — set context + run inside adapter.runWithTenant
|
|
25
|
+
* so code can use getDatabase() and run tenant-scoped queries. Use for cron, per-tenant migrations.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runAs<T>(tenantId: string, adapter: TenantAdapter, fn: (database: TenantScopedDatabase) => Promise<T>): Promise<T>;
|
|
28
|
+
/**
|
|
29
|
+
* runAsSystem(fn): run fn with a DB handle that has RLS bypass.
|
|
30
|
+
* Optionally set context so getContext() reflects system mode.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runAsSystem<T>(adapter: TenantAdapter, fn: (database: SystemDatabase) => Promise<T>): Promise<T>;
|
|
33
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,MAAM,EACN,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwBD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,gBAAgB;uBAMxC,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;2BAgB/C,MAAM,QACV,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC;0BAYS,kBAAkB,GAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;2BAWzC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;EAStD;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,EACtB,EAAE,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,OAAO,CAAC,CAAC,CAAC,GACjD,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,aAAa,EACtB,EAAE,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC,CAKZ"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { BetterTenantConfig, Tenant, ResolvableRequest, SystemDatabase } from "./types.js";
|
|
2
|
+
import { getContext, runWithTenant } from "./context.js";
|
|
3
|
+
import { getDatabase, runWithTenantAndDatabase } from "./adapter.js";
|
|
4
|
+
import { type HandleRequestOptions } from "./handle-request.js";
|
|
5
|
+
import { runAs } from "./api.js";
|
|
6
|
+
export interface TenantApi {
|
|
7
|
+
createTenant(data: {
|
|
8
|
+
name: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}): Promise<Tenant>;
|
|
11
|
+
updateTenant(tenantId: string, data: {
|
|
12
|
+
name?: string;
|
|
13
|
+
slug?: string;
|
|
14
|
+
}): Promise<Tenant>;
|
|
15
|
+
listTenants(options?: {
|
|
16
|
+
limit?: number;
|
|
17
|
+
offset?: number;
|
|
18
|
+
}): Promise<Tenant[]>;
|
|
19
|
+
deleteTenant(tenantId: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface BetterTenantInstance {
|
|
22
|
+
getContext: typeof getContext;
|
|
23
|
+
getDatabase: typeof getDatabase;
|
|
24
|
+
runWithTenant: typeof runWithTenant;
|
|
25
|
+
runWithTenantAndDatabase: typeof runWithTenantAndDatabase;
|
|
26
|
+
runAs: typeof runAs;
|
|
27
|
+
runAsSystem: <T>(fn: (database: SystemDatabase) => Promise<T>) => Promise<T>;
|
|
28
|
+
resolveTenant: (request: ResolvableRequest) => string | undefined;
|
|
29
|
+
resolveTenantAsync: (request: ResolvableRequest) => Promise<string | undefined>;
|
|
30
|
+
handleRequest: <Req extends ResolvableRequest, Result>(request: Req, next: () => Promise<Result>, options?: Omit<HandleRequestOptions<Req, Result>, "resolveTenant" | "adapter">) => Promise<Result>;
|
|
31
|
+
tenant: {
|
|
32
|
+
api: TenantApi;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates the Better Tenant instance. Config must include adapter and tenantResolver.
|
|
37
|
+
* When getTenantRepository is provided, tenant.api is available for CRUD on the tenants table.
|
|
38
|
+
*/
|
|
39
|
+
export declare function betterTenant(config: BetterTenantConfig): BetterTenantInstance;
|
|
40
|
+
//# sourceMappingURL=better-tenant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-tenant.d.ts","sourceRoot":"","sources":["../src/better-tenant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,MAAM,EACN,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,EAEN,MAAM,UAAU,CAAC;AAGlB,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GACrC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,WAAW,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;IAC1D,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7E,aAAa,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;IAClE,kBAAkB,EAAE,CAClB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC,aAAa,EAAE,CAAC,GAAG,SAAS,iBAAiB,EAAE,MAAM,EACnD,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAC3B,OAAO,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,KAC3E,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE;QAAE,GAAG,EAAE,SAAS,CAAA;KAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,oBAAoB,CAmC7E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TenantContext } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the current tenant context, or undefined when not inside runWithTenant / runWithTenantAndDatabase.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getContext(): TenantContext | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Runs fn inside a scope where getContext() returns { tenantId }.
|
|
8
|
+
* No adapter/DB involved; use for tests or when adapter is not configured.
|
|
9
|
+
* If tenantId is empty string, it is treated as undefined (no tenant).
|
|
10
|
+
*/
|
|
11
|
+
export declare function runWithTenant<T>(tenantId: string, fn: () => T | Promise<T>): Promise<T>;
|
|
12
|
+
/**
|
|
13
|
+
* Internal: set context with optional database handle. Used by runWithTenantAndDatabase.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runWithContext<T>(context: TenantContext, fn: () => T | Promise<T>): Promise<T>;
|
|
16
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD;;GAEG;AACH,wBAAgB,UAAU,IAAI,aAAa,GAAG,SAAS,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,aAAa,EACtB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAEZ"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class TenantNotResolvedError extends Error {
|
|
2
|
+
constructor(message?: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class TenantMiddlewareError extends Error {
|
|
5
|
+
constructor(message?: string, options?: {
|
|
6
|
+
cause?: unknown;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,SAA6D;CAIjF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAE5C,OAAO,SAAmD,EAC1D,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAKhC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TenantAdapter } from "./types.js";
|
|
2
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
3
|
+
export interface HandleRequestOptions<Req, Result> {
|
|
4
|
+
resolveTenant: (request: Req) => MaybePromise<string | undefined>;
|
|
5
|
+
adapter: TenantAdapter;
|
|
6
|
+
onMissingTenant?: (request: Req) => MaybePromise<Result>;
|
|
7
|
+
onError?: (error: unknown, request: Req) => MaybePromise<Result>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generic request helper for framework adapters.
|
|
11
|
+
*
|
|
12
|
+
* It resolves a tenant id from the framework request, then runs the request handler
|
|
13
|
+
* inside runWithTenantAndDatabase so both getContext() and getDatabase() are available.
|
|
14
|
+
*/
|
|
15
|
+
export declare function handleRequest<Req, Result>(request: Req, next: () => Promise<Result>, options: HandleRequestOptions<Req, Result>): Promise<Result>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=handle-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-request.d.ts","sourceRoot":"","sources":["../src/handle-request.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,oBAAoB,CAAC,GAAG,EAAE,MAAM;IAC/C,aAAa,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,YAAY,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,CAAC;IACvB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;CAClE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAC7C,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAE,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,GACzC,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
|