@usebetterdev/tenant 0.1.0 → 0.2.0-beta.17
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 +270 -0
- package/dist/drizzle.cjs +6 -2
- package/dist/drizzle.cjs.map +1 -1
- package/dist/drizzle.d.cts +2 -1
- package/dist/drizzle.d.ts +2 -1
- package/dist/drizzle.js +4 -2
- package/dist/drizzle.js.map +1 -1
- package/dist/index.cjs +0 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +0 -6
- package/dist/index.js.map +1 -1
- package/dist/prisma.cjs +31 -0
- package/dist/prisma.cjs.map +1 -0
- package/dist/prisma.d.cts +1 -0
- package/dist/prisma.d.ts +1 -0
- package/dist/prisma.js +6 -0
- package/dist/prisma.js.map +1 -0
- package/package.json +30 -7
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @usebetterdev/tenant
|
|
2
|
+
|
|
3
|
+
Multi-tenancy for Postgres in minutes. Database-enforced tenant isolation via Row-Level Security, with adapters for Hono, Express, and Next.js.
|
|
4
|
+
|
|
5
|
+
- **RLS-based isolation** — tenant boundaries enforced at the database level, not application code
|
|
6
|
+
- **Framework adapters** — Hono, Express, Next.js App Router
|
|
7
|
+
- **Drizzle ORM** — first-class adapter with transaction-scoped tenant context
|
|
8
|
+
- **CLI** — generate migrations, verify setup, seed tenants
|
|
9
|
+
- **Zero WHERE clauses** — queries are automatically scoped to the current tenant
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @usebetterdev/tenant
|
|
15
|
+
# CLI (dev dependency)
|
|
16
|
+
npm install -D @usebetterdev/tenant-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
### 1. Initialize config
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @usebetterdev/tenant-cli init --database-url $DATABASE_URL
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This detects your tables and creates `better-tenant.config.json` interactively. Or create it manually:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"tenantTables": ["projects", "tasks"]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Generate and apply migration
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx @usebetterdev/tenant-cli migrate -o ./migrations
|
|
39
|
+
psql $DATABASE_URL -f ./migrations/*_better_tenant.sql
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This creates the `tenants` table, RLS policies, and triggers for each table listed in `tenantTables`.
|
|
43
|
+
|
|
44
|
+
### 3. Verify setup
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx @usebetterdev/tenant-cli check --database-url $DATABASE_URL
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 4. Seed a tenant
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @usebetterdev/tenant-cli seed --name "Acme Corp" --database-url $DATABASE_URL
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 5. Wire up your app
|
|
57
|
+
|
|
58
|
+
**With pg:**
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
62
|
+
import { Pool } from "pg";
|
|
63
|
+
import { betterTenant } from "@usebetterdev/tenant";
|
|
64
|
+
import { drizzleDatabase } from "@usebetterdev/tenant/drizzle";
|
|
65
|
+
|
|
66
|
+
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
67
|
+
const database = drizzle(pool);
|
|
68
|
+
|
|
69
|
+
export const tenant = betterTenant({
|
|
70
|
+
database: drizzleDatabase(database),
|
|
71
|
+
tenantResolver: { header: "x-tenant-id" },
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**With postgres.js:**
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
79
|
+
import postgres from "postgres";
|
|
80
|
+
import { betterTenant } from "@usebetterdev/tenant";
|
|
81
|
+
import { drizzleDatabase } from "@usebetterdev/tenant/drizzle";
|
|
82
|
+
|
|
83
|
+
const client = postgres(process.env.DATABASE_URL);
|
|
84
|
+
const database = drizzle(client);
|
|
85
|
+
|
|
86
|
+
export const tenant = betterTenant({
|
|
87
|
+
database: drizzleDatabase(database),
|
|
88
|
+
tenantResolver: { header: "x-tenant-id" },
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 6. Add framework middleware
|
|
93
|
+
|
|
94
|
+
**Hono**
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { createHonoMiddleware } from "@usebetterdev/tenant/hono";
|
|
98
|
+
|
|
99
|
+
app.use("*", createHonoMiddleware(tenant));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Express**
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { createExpressMiddleware } from "@usebetterdev/tenant/express";
|
|
106
|
+
|
|
107
|
+
app.use(createExpressMiddleware(tenant));
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Next.js App Router**
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { withTenant } from "@usebetterdev/tenant/next";
|
|
114
|
+
|
|
115
|
+
export const GET = withTenant(tenant, async (request) => {
|
|
116
|
+
// tenant context is available here
|
|
117
|
+
return Response.json({ ok: true });
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 7. Use in handlers
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// Current tenant
|
|
125
|
+
const ctx = tenant.getContext();
|
|
126
|
+
ctx.tenantId; // "550e8400-..."
|
|
127
|
+
ctx.tenant; // { id, name, slug, createdAt }
|
|
128
|
+
|
|
129
|
+
// Tenant-scoped database (all queries filtered by RLS)
|
|
130
|
+
const db = tenant.getDatabase();
|
|
131
|
+
const projects = await db.select().from(projectsTable);
|
|
132
|
+
// ^ returns only current tenant's projects — no WHERE needed
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 8. Shared (non-tenant) tables
|
|
136
|
+
|
|
137
|
+
Tables without RLS (lookup data, settings, feature flags) work through the same `getDatabase()` handle — no separate connection needed. Wrap it for convenience:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// src/database.ts
|
|
141
|
+
import { tenant } from "./tenant";
|
|
142
|
+
|
|
143
|
+
export function getDatabase() {
|
|
144
|
+
const database = tenant.getDatabase();
|
|
145
|
+
if (!database) {
|
|
146
|
+
throw new Error("No active tenant context");
|
|
147
|
+
}
|
|
148
|
+
return database;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then use `getDatabase()` for everything:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { getDatabase } from "../database";
|
|
156
|
+
|
|
157
|
+
const projects = await getDatabase().select().from(projectsTable); // RLS-filtered
|
|
158
|
+
const categories = await getDatabase().select().from(categoriesTable); // no RLS, all rows
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Subpath exports
|
|
162
|
+
|
|
163
|
+
| Import | Description |
|
|
164
|
+
| ------------------------------ | -------------------------------------------------------------------- |
|
|
165
|
+
| `@usebetterdev/tenant` | Core API: `betterTenant`, `getContext`, `runAs`, `runAsSystem` |
|
|
166
|
+
| `@usebetterdev/tenant/drizzle` | Drizzle: `drizzleDatabase`, `tenantsTable` |
|
|
167
|
+
| `@usebetterdev/tenant/hono` | Hono middleware: `createHonoMiddleware` |
|
|
168
|
+
| `@usebetterdev/tenant/express` | Express middleware: `createExpressMiddleware` |
|
|
169
|
+
| `@usebetterdev/tenant/next` | Next.js wrapper: `withTenant` |
|
|
170
|
+
|
|
171
|
+
## Tenant resolver
|
|
172
|
+
|
|
173
|
+
Configure how the tenant ID is extracted from incoming requests. Resolution order: **header > path > subdomain > JWT > custom**.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
tenantResolver: {
|
|
177
|
+
header: "x-tenant-id", // from request header
|
|
178
|
+
path: "/t/:tenantId/*", // from URL path segment
|
|
179
|
+
subdomain: true, // from subdomain (acme.app.com)
|
|
180
|
+
jwt: { claim: "tenant_id" }, // from JWT payload
|
|
181
|
+
custom: (req) => extractTenant(req), // custom function
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Resolving by slug
|
|
186
|
+
|
|
187
|
+
Slugs are automatically resolved to UUIDs. If a resolver returns `"acme"` (not a UUID), the library looks it up in the tenants table and uses the matching UUID for RLS. No extra config needed — subdomain resolution just works:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const tenant = betterTenant({
|
|
191
|
+
database: drizzleDatabase(db),
|
|
192
|
+
tenantResolver: { subdomain: true },
|
|
193
|
+
});
|
|
194
|
+
// acme.app.com → resolves "acme" → looks up slug → uses UUID for RLS
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
For custom mappings (e.g. custom domains), use `resolveToId`:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
tenantResolver: {
|
|
201
|
+
custom: (req) => req.host, // "client.com"
|
|
202
|
+
resolveToId: async (domain) => {
|
|
203
|
+
const mapping = await lookupDomain(domain);
|
|
204
|
+
return mapping.tenantId; // UUID
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Tenant API
|
|
210
|
+
|
|
211
|
+
CRUD operations on the `tenants` table are available via `tenant.api`. All API calls run with RLS bypass (`runAsSystem`) so they can read and write tenants across the system. **Restrict these endpoints to admins** — do not expose them to regular tenant users.
|
|
212
|
+
|
|
213
|
+
| Method | Description |
|
|
214
|
+
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
215
|
+
| **createTenant(data)** | Create a tenant. `data`: `{ name: string, slug: string }` (both required, trimmed). Returns the created `Tenant` (`id`, `name`, `slug`, `createdAt`). |
|
|
216
|
+
| **listTenants(options?)** | List tenants with pagination. `options`: `{ limit?: number, offset?: number }`. Default `limit` 50. Returns `Tenant[]`. |
|
|
217
|
+
| **updateTenant(tenantId, data)** | Update a tenant by ID. `data`: `{ name?: string, slug?: string }`. Returns the updated `Tenant`. |
|
|
218
|
+
| **deleteTenant(tenantId)** | Delete a tenant by ID. Returns `void`. |
|
|
219
|
+
|
|
220
|
+
Example:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
// Create
|
|
224
|
+
const created = await tenant.api.createTenant({
|
|
225
|
+
name: "Acme Corp",
|
|
226
|
+
slug: "acme",
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// List (e.g. admin dashboard)
|
|
230
|
+
const tenants = await tenant.api.listTenants({ limit: 20, offset: 0 });
|
|
231
|
+
|
|
232
|
+
// Update
|
|
233
|
+
await tenant.api.updateTenant(created.id, {
|
|
234
|
+
name: "Acme Inc",
|
|
235
|
+
slug: "acme-inc",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Delete
|
|
239
|
+
await tenant.api.deleteTenant(created.id);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Admin operations
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
// Run as a specific tenant (cron jobs, background tasks)
|
|
246
|
+
await tenant.runAs(tenantId, async (db) => {
|
|
247
|
+
await db.select().from(projectsTable); // scoped to tenant
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Run with RLS bypass (admin, cross-tenant reporting)
|
|
251
|
+
await tenant.runAsSystem(async (db) => {
|
|
252
|
+
await db.select().from(projectsTable); // all tenants
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## How it works
|
|
257
|
+
|
|
258
|
+
1. Request arrives with tenant identifier (header, path, subdomain, JWT, or custom)
|
|
259
|
+
2. Middleware resolves the tenant ID and starts a database transaction
|
|
260
|
+
3. `SET LOCAL app.current_tenant = '<uuid>'` scopes all queries via RLS
|
|
261
|
+
4. Your handler runs — every query is automatically filtered to the current tenant
|
|
262
|
+
5. Transaction commits, `SET LOCAL` auto-clears (safe for connection pooling)
|
|
263
|
+
|
|
264
|
+
## Telemetry
|
|
265
|
+
|
|
266
|
+
Anonymous telemetry is on by default. Opt out with `BETTER_TENANT_TELEMETRY=0` or `telemetry: { enabled: false }` in config.
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
package/dist/drizzle.cjs
CHANGED
|
@@ -20,12 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/drizzle.ts
|
|
21
21
|
var drizzle_exports = {};
|
|
22
22
|
__export(drizzle_exports, {
|
|
23
|
-
|
|
23
|
+
drizzleDatabase: () => import_tenant_drizzle.drizzleDatabase,
|
|
24
|
+
tenantId: () => import_tenant_drizzle.tenantId,
|
|
25
|
+
tenantsTable: () => import_tenant_drizzle.tenantsTable
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(drizzle_exports);
|
|
26
28
|
var import_tenant_drizzle = require("@usebetterdev/tenant-drizzle");
|
|
27
29
|
// Annotate the CommonJS export names for ESM import in node:
|
|
28
30
|
0 && (module.exports = {
|
|
29
|
-
|
|
31
|
+
drizzleDatabase,
|
|
32
|
+
tenantId,
|
|
33
|
+
tenantsTable
|
|
30
34
|
});
|
|
31
35
|
//# sourceMappingURL=drizzle.cjs.map
|
package/dist/drizzle.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/drizzle.ts"],"sourcesContent":["export {
|
|
1
|
+
{"version":3,"sources":["../src/drizzle.ts"],"sourcesContent":["export { drizzleDatabase, tenantsTable, tenantId } from \"@usebetterdev/tenant-drizzle\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAwD;","names":[]}
|
package/dist/drizzle.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { drizzleDatabase, tenantId, tenantsTable } from '@usebetterdev/tenant-drizzle';
|
|
2
2
|
import '@usebetterdev/tenant-express';
|
|
3
3
|
import '@usebetterdev/tenant-hono';
|
|
4
4
|
import '@usebetterdev/tenant-core';
|
|
5
5
|
import '@usebetterdev/tenant-next';
|
|
6
|
+
import '@usebetterdev/tenant-prisma';
|
package/dist/drizzle.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { drizzleDatabase, tenantId, tenantsTable } from '@usebetterdev/tenant-drizzle';
|
|
2
2
|
import '@usebetterdev/tenant-express';
|
|
3
3
|
import '@usebetterdev/tenant-hono';
|
|
4
4
|
import '@usebetterdev/tenant-core';
|
|
5
5
|
import '@usebetterdev/tenant-next';
|
|
6
|
+
import '@usebetterdev/tenant-prisma';
|
package/dist/drizzle.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/drizzle.ts
|
|
2
|
-
import {
|
|
2
|
+
import { drizzleDatabase, tenantsTable, tenantId } from "@usebetterdev/tenant-drizzle";
|
|
3
3
|
export {
|
|
4
|
-
|
|
4
|
+
drizzleDatabase,
|
|
5
|
+
tenantId,
|
|
6
|
+
tenantsTable
|
|
5
7
|
};
|
|
6
8
|
//# sourceMappingURL=drizzle.js.map
|
package/dist/drizzle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/drizzle.ts"],"sourcesContent":["export {
|
|
1
|
+
{"version":3,"sources":["../src/drizzle.ts"],"sourcesContent":["export { drizzleDatabase, tenantsTable, tenantId } from \"@usebetterdev/tenant-drizzle\";\n"],"mappings":";AAAA,SAAS,iBAAiB,cAAc,gBAAgB;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -25,14 +25,11 @@ __export(index_exports, {
|
|
|
25
25
|
betterTenant: () => import_tenant_core.betterTenant,
|
|
26
26
|
createTenantApi: () => import_tenant_core.createTenantApi,
|
|
27
27
|
getContext: () => import_tenant_core.getContext,
|
|
28
|
-
getDatabase: () => import_tenant_core.getDatabase,
|
|
29
28
|
handleRequest: () => import_tenant_core.handleRequest,
|
|
30
29
|
resolveTenant: () => import_tenant_core.resolveTenant,
|
|
31
|
-
resolveTenantAsync: () => import_tenant_core.resolveTenantAsync,
|
|
32
30
|
runAs: () => import_tenant_core.runAs,
|
|
33
31
|
runAsSystem: () => import_tenant_core.runAsSystem,
|
|
34
32
|
runWithTenant: () => import_tenant_core.runWithTenant,
|
|
35
|
-
runWithTenantAndDatabase: () => import_tenant_core.runWithTenantAndDatabase,
|
|
36
33
|
toResolvableRequest: () => import_tenant_core.toResolvableRequest
|
|
37
34
|
});
|
|
38
35
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -44,14 +41,11 @@ var import_tenant_core = require("@usebetterdev/tenant-core");
|
|
|
44
41
|
betterTenant,
|
|
45
42
|
createTenantApi,
|
|
46
43
|
getContext,
|
|
47
|
-
getDatabase,
|
|
48
44
|
handleRequest,
|
|
49
45
|
resolveTenant,
|
|
50
|
-
resolveTenantAsync,
|
|
51
46
|
runAs,
|
|
52
47
|
runAsSystem,
|
|
53
48
|
runWithTenant,
|
|
54
|
-
runWithTenantAndDatabase,
|
|
55
49
|
toResolvableRequest
|
|
56
50
|
});
|
|
57
51
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n betterTenant,\n getContext,\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n betterTenant,\n getContext,\n runWithTenant,\n resolveTenant,\n handleRequest,\n toResolvableRequest,\n runAs,\n runAsSystem,\n createTenantApi,\n TenantNotResolvedError,\n TenantMiddlewareError,\n} from \"@usebetterdev/tenant-core\";\nexport type {\n BetterTenantInstance,\n TenantApi,\n CreateTenantData,\n UpdateTenantData,\n ListTenantsOptions,\n HandleRequestOptions,\n Tenant,\n TenantContext,\n TenantScopedDatabase,\n SystemDatabase,\n TenantAdapter,\n TenantRepository,\n DatabaseProvider,\n TenantResolverConfig,\n ResolvableRequest,\n BetterTenantPlugin,\n BetterTenantConfig,\n NodeLikeRequest,\n PathResolverConfig,\n SubdomainResolverConfig,\n JwtResolverConfig,\n} from \"@usebetterdev/tenant-core\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAYO;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { BetterTenantConfig, BetterTenantInstance, BetterTenantPlugin, CreateTenantData, HandleRequestOptions, JwtResolverConfig, ListTenantsOptions, NodeLikeRequest, PathResolverConfig, ResolvableRequest, SubdomainResolverConfig, SystemDatabase, Tenant, TenantAdapter, TenantApi, TenantContext, TenantMiddlewareError, TenantNotResolvedError, TenantRepository, TenantResolverConfig, TenantScopedDatabase, UpdateTenantData, betterTenant, createTenantApi, getContext,
|
|
1
|
+
export { BetterTenantConfig, BetterTenantInstance, BetterTenantPlugin, CreateTenantData, DatabaseProvider, HandleRequestOptions, JwtResolverConfig, ListTenantsOptions, NodeLikeRequest, PathResolverConfig, ResolvableRequest, SubdomainResolverConfig, SystemDatabase, Tenant, TenantAdapter, TenantApi, TenantContext, TenantMiddlewareError, TenantNotResolvedError, TenantRepository, TenantResolverConfig, TenantScopedDatabase, UpdateTenantData, betterTenant, createTenantApi, getContext, handleRequest, resolveTenant, runAs, runAsSystem, runWithTenant, toResolvableRequest } from '@usebetterdev/tenant-core';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { BetterTenantConfig, BetterTenantInstance, BetterTenantPlugin, CreateTenantData, HandleRequestOptions, JwtResolverConfig, ListTenantsOptions, NodeLikeRequest, PathResolverConfig, ResolvableRequest, SubdomainResolverConfig, SystemDatabase, Tenant, TenantAdapter, TenantApi, TenantContext, TenantMiddlewareError, TenantNotResolvedError, TenantRepository, TenantResolverConfig, TenantScopedDatabase, UpdateTenantData, betterTenant, createTenantApi, getContext,
|
|
1
|
+
export { BetterTenantConfig, BetterTenantInstance, BetterTenantPlugin, CreateTenantData, DatabaseProvider, HandleRequestOptions, JwtResolverConfig, ListTenantsOptions, NodeLikeRequest, PathResolverConfig, ResolvableRequest, SubdomainResolverConfig, SystemDatabase, Tenant, TenantAdapter, TenantApi, TenantContext, TenantMiddlewareError, TenantNotResolvedError, TenantRepository, TenantResolverConfig, TenantScopedDatabase, UpdateTenantData, betterTenant, createTenantApi, getContext, handleRequest, resolveTenant, runAs, runAsSystem, runWithTenant, toResolvableRequest } from '@usebetterdev/tenant-core';
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
betterTenant,
|
|
4
4
|
getContext,
|
|
5
|
-
getDatabase,
|
|
6
5
|
runWithTenant,
|
|
7
|
-
runWithTenantAndDatabase,
|
|
8
6
|
resolveTenant,
|
|
9
|
-
resolveTenantAsync,
|
|
10
7
|
handleRequest,
|
|
11
8
|
toResolvableRequest,
|
|
12
9
|
runAs,
|
|
@@ -21,14 +18,11 @@ export {
|
|
|
21
18
|
betterTenant,
|
|
22
19
|
createTenantApi,
|
|
23
20
|
getContext,
|
|
24
|
-
getDatabase,
|
|
25
21
|
handleRequest,
|
|
26
22
|
resolveTenant,
|
|
27
|
-
resolveTenantAsync,
|
|
28
23
|
runAs,
|
|
29
24
|
runAsSystem,
|
|
30
25
|
runWithTenant,
|
|
31
|
-
runWithTenantAndDatabase,
|
|
32
26
|
toResolvableRequest
|
|
33
27
|
};
|
|
34
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n betterTenant,\n getContext,\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n betterTenant,\n getContext,\n runWithTenant,\n resolveTenant,\n handleRequest,\n toResolvableRequest,\n runAs,\n runAsSystem,\n createTenantApi,\n TenantNotResolvedError,\n TenantMiddlewareError,\n} from \"@usebetterdev/tenant-core\";\nexport type {\n BetterTenantInstance,\n TenantApi,\n CreateTenantData,\n UpdateTenantData,\n ListTenantsOptions,\n HandleRequestOptions,\n Tenant,\n TenantContext,\n TenantScopedDatabase,\n SystemDatabase,\n TenantAdapter,\n TenantRepository,\n DatabaseProvider,\n TenantResolverConfig,\n ResolvableRequest,\n BetterTenantPlugin,\n BetterTenantConfig,\n NodeLikeRequest,\n PathResolverConfig,\n SubdomainResolverConfig,\n JwtResolverConfig,\n} from \"@usebetterdev/tenant-core\";\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
|
package/dist/prisma.cjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/prisma.ts
|
|
21
|
+
var prisma_exports = {};
|
|
22
|
+
__export(prisma_exports, {
|
|
23
|
+
prismaDatabase: () => import_tenant_prisma.prismaDatabase
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(prisma_exports);
|
|
26
|
+
var import_tenant_prisma = require("@usebetterdev/tenant-prisma");
|
|
27
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
28
|
+
0 && (module.exports = {
|
|
29
|
+
prismaDatabase
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=prisma.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prisma.ts"],"sourcesContent":["export { prismaDatabase } from \"@usebetterdev/tenant-prisma\";\nexport type { PrismaClientLike, PrismaTransactionClient } from \"@usebetterdev/tenant-prisma\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA+B;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PrismaClientLike, PrismaTransactionClient, prismaDatabase } from '@usebetterdev/tenant-prisma';
|
package/dist/prisma.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PrismaClientLike, PrismaTransactionClient, prismaDatabase } from '@usebetterdev/tenant-prisma';
|
package/dist/prisma.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prisma.ts"],"sourcesContent":["export { prismaDatabase } from \"@usebetterdev/tenant-prisma\";\nexport type { PrismaClientLike, PrismaTransactionClient } from \"@usebetterdev/tenant-prisma\";\n"],"mappings":";AAAA,SAAS,sBAAsB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebetterdev/tenant",
|
|
3
|
-
"
|
|
3
|
+
"description": "Multi-tenancy for Postgres in minutes. RLS-based tenant isolation, framework adapters (Hono, Express, Next.js), Drizzle and Prisma ORM support.",
|
|
4
|
+
"version": "0.2.0-beta.17",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"multi-tenancy",
|
|
7
|
+
"postgres",
|
|
8
|
+
"rls",
|
|
9
|
+
"row-level-security",
|
|
10
|
+
"tenant",
|
|
11
|
+
"drizzle",
|
|
12
|
+
"prisma",
|
|
13
|
+
"hono",
|
|
14
|
+
"express",
|
|
15
|
+
"nextjs",
|
|
16
|
+
"saas"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
4
19
|
"repository": "github:usebetter-dev/usebetter",
|
|
5
20
|
"bugs": "https://github.com/usebetter-dev/usebetter/issues",
|
|
6
21
|
"homepage": "https://github.com/usebetter-dev/usebetter#readme",
|
|
@@ -39,17 +54,25 @@
|
|
|
39
54
|
"import": "./dist/next.js",
|
|
40
55
|
"require": "./dist/next.cjs",
|
|
41
56
|
"default": "./dist/next.js"
|
|
57
|
+
},
|
|
58
|
+
"./prisma": {
|
|
59
|
+
"types": "./dist/prisma.d.ts",
|
|
60
|
+
"import": "./dist/prisma.js",
|
|
61
|
+
"require": "./dist/prisma.cjs",
|
|
62
|
+
"default": "./dist/prisma.js"
|
|
42
63
|
}
|
|
43
64
|
},
|
|
44
65
|
"files": [
|
|
45
|
-
"dist"
|
|
66
|
+
"dist",
|
|
67
|
+
"README.md"
|
|
46
68
|
],
|
|
47
69
|
"dependencies": {
|
|
48
|
-
"@usebetterdev/tenant-
|
|
49
|
-
"@usebetterdev/tenant-
|
|
50
|
-
"@usebetterdev/tenant-
|
|
51
|
-
"@usebetterdev/tenant-
|
|
52
|
-
"@usebetterdev/tenant-next": "0.
|
|
70
|
+
"@usebetterdev/tenant-core": "0.2.0-beta.17",
|
|
71
|
+
"@usebetterdev/tenant-drizzle": "0.2.0-beta.17",
|
|
72
|
+
"@usebetterdev/tenant-express": "0.2.0-beta.17",
|
|
73
|
+
"@usebetterdev/tenant-hono": "0.2.0-beta.17",
|
|
74
|
+
"@usebetterdev/tenant-next": "0.2.0-beta.17",
|
|
75
|
+
"@usebetterdev/tenant-prisma": "0.2.0-beta.17"
|
|
53
76
|
},
|
|
54
77
|
"devDependencies": {
|
|
55
78
|
"tsup": "^8.3.5",
|