drizzle-multitenant 1.0.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/.claude/settings.local.json +14 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/bin/drizzle-multitenant.js +2 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +866 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context-DBerWr50.d.ts +76 -0
- package/dist/cross-schema/index.d.ts +262 -0
- package/dist/cross-schema/index.js +219 -0
- package/dist/cross-schema/index.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +935 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/express.d.ts +93 -0
- package/dist/integrations/express.js +110 -0
- package/dist/integrations/express.js.map +1 -0
- package/dist/integrations/fastify.d.ts +92 -0
- package/dist/integrations/fastify.js +236 -0
- package/dist/integrations/fastify.js.map +1 -0
- package/dist/integrations/hono.d.ts +2 -0
- package/dist/integrations/hono.js +3 -0
- package/dist/integrations/hono.js.map +1 -0
- package/dist/integrations/nestjs/index.d.ts +386 -0
- package/dist/integrations/nestjs/index.js +9828 -0
- package/dist/integrations/nestjs/index.js.map +1 -0
- package/dist/migrator/index.d.ts +208 -0
- package/dist/migrator/index.js +390 -0
- package/dist/migrator/index.js.map +1 -0
- package/dist/types-DKVaTaIb.d.ts +130 -0
- package/package.json +102 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { PoolConfig, Pool } from 'pg';
|
|
2
|
+
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Isolation strategy for multi-tenancy
|
|
6
|
+
*/
|
|
7
|
+
type IsolationStrategy = 'schema' | 'database' | 'row';
|
|
8
|
+
/**
|
|
9
|
+
* Connection configuration
|
|
10
|
+
*/
|
|
11
|
+
interface ConnectionConfig {
|
|
12
|
+
/** PostgreSQL connection URL */
|
|
13
|
+
url: string;
|
|
14
|
+
/** Pool configuration options */
|
|
15
|
+
poolConfig?: Omit<PoolConfig, 'connectionString'>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Isolation configuration
|
|
19
|
+
*/
|
|
20
|
+
interface IsolationConfig {
|
|
21
|
+
/** Isolation strategy (currently only 'schema' is supported) */
|
|
22
|
+
strategy: IsolationStrategy;
|
|
23
|
+
/** Function to generate schema name from tenant ID */
|
|
24
|
+
schemaNameTemplate: (tenantId: string) => string;
|
|
25
|
+
/** Maximum number of simultaneous pools (LRU eviction) */
|
|
26
|
+
maxPools?: number;
|
|
27
|
+
/** TTL in milliseconds before pool cleanup */
|
|
28
|
+
poolTtlMs?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Schema definitions
|
|
32
|
+
*/
|
|
33
|
+
interface SchemasConfig<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
34
|
+
/** Schema applied per tenant */
|
|
35
|
+
tenant: TTenantSchema;
|
|
36
|
+
/** Shared schema (public) */
|
|
37
|
+
shared?: TSharedSchema;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Lifecycle hooks
|
|
41
|
+
*/
|
|
42
|
+
interface Hooks {
|
|
43
|
+
/** Called when a new pool is created */
|
|
44
|
+
onPoolCreated?: (tenantId: string) => void | Promise<void>;
|
|
45
|
+
/** Called when a pool is evicted */
|
|
46
|
+
onPoolEvicted?: (tenantId: string) => void | Promise<void>;
|
|
47
|
+
/** Called on pool error */
|
|
48
|
+
onError?: (tenantId: string, error: Error) => void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Metrics configuration
|
|
52
|
+
*/
|
|
53
|
+
interface MetricsConfig {
|
|
54
|
+
/** Enable metrics collection */
|
|
55
|
+
enabled: boolean;
|
|
56
|
+
/** Prefix for metric names */
|
|
57
|
+
prefix?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Main configuration interface
|
|
61
|
+
*/
|
|
62
|
+
interface Config<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
63
|
+
/** Database connection settings */
|
|
64
|
+
connection: ConnectionConfig;
|
|
65
|
+
/** Tenant isolation settings */
|
|
66
|
+
isolation: IsolationConfig;
|
|
67
|
+
/** Drizzle schemas */
|
|
68
|
+
schemas: SchemasConfig<TTenantSchema, TSharedSchema>;
|
|
69
|
+
/** Lifecycle hooks */
|
|
70
|
+
hooks?: Hooks;
|
|
71
|
+
/** Metrics configuration */
|
|
72
|
+
metrics?: MetricsConfig;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Internal pool entry for LRU cache
|
|
76
|
+
*/
|
|
77
|
+
interface PoolEntry<TSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
78
|
+
/** Drizzle database instance */
|
|
79
|
+
db: NodePgDatabase<TSchema>;
|
|
80
|
+
/** PostgreSQL pool */
|
|
81
|
+
pool: Pool;
|
|
82
|
+
/** Last access timestamp */
|
|
83
|
+
lastAccess: number;
|
|
84
|
+
/** Schema name */
|
|
85
|
+
schemaName: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Type for tenant database instance
|
|
89
|
+
*/
|
|
90
|
+
type TenantDb<TSchema extends Record<string, unknown> = Record<string, unknown>> = NodePgDatabase<TSchema>;
|
|
91
|
+
/**
|
|
92
|
+
* Type for shared database instance
|
|
93
|
+
*/
|
|
94
|
+
type SharedDb<TSchema extends Record<string, unknown> = Record<string, unknown>> = NodePgDatabase<TSchema>;
|
|
95
|
+
/**
|
|
96
|
+
* Tenant manager interface
|
|
97
|
+
*/
|
|
98
|
+
interface TenantManager<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
99
|
+
/** Get database instance for a specific tenant */
|
|
100
|
+
getDb(tenantId: string): TenantDb<TTenantSchema>;
|
|
101
|
+
/** Get shared database instance */
|
|
102
|
+
getSharedDb(): SharedDb<TSharedSchema>;
|
|
103
|
+
/** Get the schema name for a tenant */
|
|
104
|
+
getSchemaName(tenantId: string): string;
|
|
105
|
+
/** Check if a tenant pool exists */
|
|
106
|
+
hasPool(tenantId: string): boolean;
|
|
107
|
+
/** Get active pool count */
|
|
108
|
+
getPoolCount(): number;
|
|
109
|
+
/** Get all active tenant IDs */
|
|
110
|
+
getActiveTenantIds(): string[];
|
|
111
|
+
/** Manually evict a tenant pool */
|
|
112
|
+
evictPool(tenantId: string): Promise<void>;
|
|
113
|
+
/** Dispose all pools and cleanup */
|
|
114
|
+
dispose(): Promise<void>;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Default configuration values
|
|
118
|
+
*/
|
|
119
|
+
declare const DEFAULT_CONFIG: {
|
|
120
|
+
readonly maxPools: 50;
|
|
121
|
+
readonly poolTtlMs: number;
|
|
122
|
+
readonly cleanupIntervalMs: 60000;
|
|
123
|
+
readonly poolConfig: {
|
|
124
|
+
readonly max: 10;
|
|
125
|
+
readonly idleTimeoutMillis: 30000;
|
|
126
|
+
readonly connectionTimeoutMillis: 5000;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export { type Config as C, DEFAULT_CONFIG as D, type Hooks as H, type IsolationConfig as I, type MetricsConfig as M, type PoolEntry as P, type SharedDb as S, type TenantManager as T, type TenantDb as a, type ConnectionConfig as b, type IsolationStrategy as c, type SchemasConfig as d };
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "drizzle-multitenant",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Multi-tenancy toolkit for Drizzle ORM with schema isolation, tenant context, and parallel migrations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./express": {
|
|
15
|
+
"import": "./dist/integrations/express.js",
|
|
16
|
+
"types": "./dist/integrations/express.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./fastify": {
|
|
19
|
+
"import": "./dist/integrations/fastify.js",
|
|
20
|
+
"types": "./dist/integrations/fastify.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./nestjs": {
|
|
23
|
+
"import": "./dist/integrations/nestjs/index.js",
|
|
24
|
+
"types": "./dist/integrations/nestjs/index.d.ts"
|
|
25
|
+
},
|
|
26
|
+
"./hono": {
|
|
27
|
+
"import": "./dist/integrations/hono.js",
|
|
28
|
+
"types": "./dist/integrations/hono.d.ts"
|
|
29
|
+
},
|
|
30
|
+
"./migrator": {
|
|
31
|
+
"import": "./dist/migrator/index.js",
|
|
32
|
+
"types": "./dist/migrator/index.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./cross-schema": {
|
|
35
|
+
"import": "./dist/cross-schema/index.js",
|
|
36
|
+
"types": "./dist/cross-schema/index.d.ts"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"bin": {
|
|
40
|
+
"drizzle-multitenant": "./bin/drizzle-multitenant.js"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"test": "vitest",
|
|
46
|
+
"test:coverage": "vitest --coverage",
|
|
47
|
+
"lint": "eslint src --ext .ts",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"prepublishOnly": "npm run build"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"drizzle",
|
|
53
|
+
"drizzle-orm",
|
|
54
|
+
"multi-tenant",
|
|
55
|
+
"multitenancy",
|
|
56
|
+
"postgresql",
|
|
57
|
+
"schema-isolation",
|
|
58
|
+
"saas"
|
|
59
|
+
],
|
|
60
|
+
"author": "Mateus Florez",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "git+https://github.com/mateusflorez/drizzle-multitenant.git"
|
|
65
|
+
},
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "https://github.com/mateusflorez/drizzle-multitenant/issues"
|
|
68
|
+
},
|
|
69
|
+
"homepage": "https://github.com/mateusflorez/drizzle-multitenant#readme",
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"chalk": "^5.6.2",
|
|
72
|
+
"cli-table3": "^0.6.5",
|
|
73
|
+
"commander": "^12.1.0",
|
|
74
|
+
"lru-cache": "^10.4.3",
|
|
75
|
+
"ora": "^8.2.0"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"drizzle-orm": ">=0.29.0",
|
|
79
|
+
"pg": ">=8.0.0"
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@nestjs/common": "^10.4.20",
|
|
83
|
+
"@nestjs/core": "^10.4.20",
|
|
84
|
+
"@nestjs/testing": "^10.4.20",
|
|
85
|
+
"@types/express": "^5.0.6",
|
|
86
|
+
"@types/node": "^22.10.2",
|
|
87
|
+
"@types/pg": "^8.11.10",
|
|
88
|
+
"drizzle-orm": "^0.38.2",
|
|
89
|
+
"express": "^5.2.1",
|
|
90
|
+
"fastify": "^5.6.2",
|
|
91
|
+
"fastify-plugin": "^5.1.0",
|
|
92
|
+
"pg": "^8.13.1",
|
|
93
|
+
"reflect-metadata": "^0.2.2",
|
|
94
|
+
"rxjs": "^7.8.2",
|
|
95
|
+
"tsup": "^8.3.5",
|
|
96
|
+
"typescript": "^5.7.2",
|
|
97
|
+
"vitest": "^2.1.8"
|
|
98
|
+
},
|
|
99
|
+
"engines": {
|
|
100
|
+
"node": ">=18.0.0"
|
|
101
|
+
}
|
|
102
|
+
}
|