tenanso 0.1.0 → 0.2.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/README.md +13 -16
- package/dist/connection-pool.d.ts +1 -0
- package/dist/connection-pool.d.ts.map +1 -1
- package/dist/connection-pool.js +3 -1
- package/dist/connection-pool.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,20 +8,27 @@ Inspired by Rails 8's [activerecord-tenanted](https://github.com/basecamp/active
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- **Database-per-tenant isolation** — each tenant's data is physically separated
|
|
12
|
-
- **Runtime-agnostic** —
|
|
11
|
+
- **Database-per-tenant isolation** — each tenant's data is physically separated, no `WHERE tenant_id = ?` needed
|
|
12
|
+
- **Runtime-agnostic** — core uses only `fetch` and `Map`, no `node:` imports. Works on Cloudflare Workers, Deno, Bun, and Node.js
|
|
13
13
|
- **Turso Platform API integration** — create and delete tenant databases dynamically
|
|
14
|
-
- **
|
|
15
|
-
- **Hono middleware** — optional first-class integration
|
|
14
|
+
- **LRU connection pooling** — caps memory and file descriptor usage with configurable `maxConnections` (default 50)
|
|
15
|
+
- **Hono middleware** — optional peer dependency with first-class integration. `import "tenanso"` has zero Hono imports
|
|
16
16
|
- **Type-safe** — full TypeScript support with Drizzle's type inference
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
+
npm install tenanso drizzle-orm @libsql/client
|
|
22
|
+
# or
|
|
21
23
|
pnpm add tenanso drizzle-orm @libsql/client
|
|
24
|
+
# or
|
|
25
|
+
yarn add tenanso drizzle-orm @libsql/client
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If using the Hono middleware:
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
```bash
|
|
31
|
+
npm install hono
|
|
25
32
|
```
|
|
26
33
|
|
|
27
34
|
## Quick Start
|
|
@@ -248,16 +255,6 @@ npx drizzle-kit push --url libsql://seed-db-my-app-my-account.turso.io --auth-to
|
|
|
248
255
|
|
|
249
256
|
See the [Turso Setup guide](/guide/turso-setup) for more details.
|
|
250
257
|
|
|
251
|
-
## Design Decisions
|
|
252
|
-
|
|
253
|
-
| Decision | Rationale |
|
|
254
|
-
|---|---|
|
|
255
|
-
| No Node.js runtime dependency | Core uses `fetch` and `Map` only. Works on Cloudflare Workers, Deno, Bun. |
|
|
256
|
-
| No built-in async context | Core passes `db` explicitly. Framework adapters (Hono's `contextStorage()`) handle implicit context. |
|
|
257
|
-
| Hono as optional peer dependency | `import "tenanso"` has zero hono imports. Only `import "tenanso/hono"` requires it. |
|
|
258
|
-
| LRU connection pool | Caps memory/file descriptor usage. Configurable via `maxConnections` (default 50). |
|
|
259
|
-
| Auth is out of scope | tenanso resolves tenants, not users. Compose with your auth stack via the `resolve` function. |
|
|
260
|
-
|
|
261
258
|
## License
|
|
262
259
|
|
|
263
260
|
MIT
|
|
@@ -5,6 +5,7 @@ export declare class ConnectionPool {
|
|
|
5
5
|
private readonly authToken;
|
|
6
6
|
private readonly schema;
|
|
7
7
|
private readonly maxConnections;
|
|
8
|
+
private readonly drizzleOptions;
|
|
8
9
|
constructor(config: TenansoConfig);
|
|
9
10
|
getDb(tenant: string): DrizzleDb;
|
|
10
11
|
remove(tenant: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-pool.d.ts","sourceRoot":"","sources":["../src/connection-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ3D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;
|
|
1
|
+
{"version":3,"file":"connection-pool.d.ts","sourceRoot":"","sources":["../src/connection-pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ3D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;gBAE7C,MAAM,EAAE,aAAa;IAQjC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAoBhC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ5B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,aAAa;CAiBtB"}
|
package/dist/connection-pool.js
CHANGED
|
@@ -6,11 +6,13 @@ export class ConnectionPool {
|
|
|
6
6
|
authToken;
|
|
7
7
|
schema;
|
|
8
8
|
maxConnections;
|
|
9
|
+
drizzleOptions;
|
|
9
10
|
constructor(config) {
|
|
10
11
|
this.databaseUrl = config.databaseUrl;
|
|
11
12
|
this.authToken = config.authToken || undefined;
|
|
12
13
|
this.schema = config.schema;
|
|
13
14
|
this.maxConnections = config.maxConnections ?? 50;
|
|
15
|
+
this.drizzleOptions = config.drizzleOptions ?? {};
|
|
14
16
|
}
|
|
15
17
|
getDb(tenant) {
|
|
16
18
|
const existing = this.cache.get(tenant);
|
|
@@ -24,7 +26,7 @@ export class ConnectionPool {
|
|
|
24
26
|
url,
|
|
25
27
|
...(this.authToken ? { authToken: this.authToken } : {}),
|
|
26
28
|
});
|
|
27
|
-
const db = drizzle(client, { schema: this.schema });
|
|
29
|
+
const db = drizzle(client, { ...this.drizzleOptions, schema: this.schema });
|
|
28
30
|
this.cache.set(tenant, { client, db, lastUsed: Date.now() });
|
|
29
31
|
return db;
|
|
30
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-pool.js","sourceRoot":"","sources":["../src/connection-pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAe,MAAM,gBAAgB,CAAC;AAS3D,MAAM,OAAO,cAAc;IACR,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IACrC,WAAW,CAAS;IACpB,SAAS,CAAqB;IAC9B,MAAM,CAA0B;IAChC,cAAc,CAAS;
|
|
1
|
+
{"version":3,"file":"connection-pool.js","sourceRoot":"","sources":["../src/connection-pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAe,MAAM,gBAAgB,CAAC;AAS3D,MAAM,OAAO,cAAc;IACR,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IACrC,WAAW,CAAS;IACpB,SAAS,CAAqB;IAC9B,MAAM,CAA0B;IAChC,cAAc,CAAS;IACvB,cAAc,CAA0B;IAEzD,YAAY,MAAqB;QAC/B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAc;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,YAAY,CAAC;YAC1B,GAAG;YACH,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5E,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC7D,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,MAAc;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,cAAc;YAAE,OAAO;QAElD,IAAI,SAA6B,CAAC;QAClC,IAAI,UAAU,GAAG,QAAQ,CAAC;QAE1B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,QAAQ,GAAG,UAAU,EAAE,CAAC;gBAChC,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC;gBAC5B,SAAS,GAAG,GAAG,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;CACF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -186,6 +186,22 @@ export interface TenansoConfig {
|
|
|
186
186
|
* @defaultValue 50
|
|
187
187
|
*/
|
|
188
188
|
maxConnections?: number | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* Additional options passed to `drizzle()` when creating database instances.
|
|
191
|
+
*
|
|
192
|
+
* Use this to configure Drizzle ORM behavior such as column name casing.
|
|
193
|
+
* The `schema` option is always set from {@link TenansoConfig.schema} and
|
|
194
|
+
* cannot be overridden here.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const tenanso = createTenanso({
|
|
199
|
+
* // ...
|
|
200
|
+
* drizzleOptions: { casing: "snake_case" },
|
|
201
|
+
* });
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
drizzleOptions?: Record<string, unknown> | undefined;
|
|
189
205
|
}
|
|
190
206
|
/**
|
|
191
207
|
* The main tenanso instance returned by {@link createTenanso}.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,KAAK,EAAE,WAAW,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,KAAK,EAAE,WAAW,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjC;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9E"}
|