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.
@@ -0,0 +1,236 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
2
+
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ __defProp(target, "default", { value: mod, enumerable: true }) ,
26
+ mod
27
+ ));
28
+
29
+ // node_modules/fastify-plugin/lib/getPluginName.js
30
+ var require_getPluginName = __commonJS({
31
+ "node_modules/fastify-plugin/lib/getPluginName.js"(exports$1, module) {
32
+ var fpStackTracePattern = /at\s(?:.*\.)?plugin\s.*\n\s*(.*)/;
33
+ var fileNamePattern = /(\w*(\.\w*)*)\..*/;
34
+ module.exports = function getPluginName(fn) {
35
+ if (fn.name.length > 0) return fn.name;
36
+ const stackTraceLimit = Error.stackTraceLimit;
37
+ Error.stackTraceLimit = 10;
38
+ try {
39
+ throw new Error("anonymous function");
40
+ } catch (e) {
41
+ Error.stackTraceLimit = stackTraceLimit;
42
+ return extractPluginName(e.stack);
43
+ }
44
+ };
45
+ function extractPluginName(stack) {
46
+ const m = stack.match(fpStackTracePattern);
47
+ return m ? m[1].split(/[/\\]/).slice(-1)[0].match(fileNamePattern)[1] : "anonymous";
48
+ }
49
+ module.exports.extractPluginName = extractPluginName;
50
+ }
51
+ });
52
+
53
+ // node_modules/fastify-plugin/lib/toCamelCase.js
54
+ var require_toCamelCase = __commonJS({
55
+ "node_modules/fastify-plugin/lib/toCamelCase.js"(exports$1, module) {
56
+ module.exports = function toCamelCase(name) {
57
+ if (name[0] === "@") {
58
+ name = name.slice(1).replace("/", "-");
59
+ }
60
+ return name.replace(/-(.)/g, function(match, g1) {
61
+ return g1.toUpperCase();
62
+ });
63
+ };
64
+ }
65
+ });
66
+
67
+ // node_modules/fastify-plugin/plugin.js
68
+ var require_plugin = __commonJS({
69
+ "node_modules/fastify-plugin/plugin.js"(exports$1, module) {
70
+ var getPluginName = require_getPluginName();
71
+ var toCamelCase = require_toCamelCase();
72
+ var count = 0;
73
+ function plugin(fn, options = {}) {
74
+ let autoName = false;
75
+ if (fn.default !== void 0) {
76
+ fn = fn.default;
77
+ }
78
+ if (typeof fn !== "function") {
79
+ throw new TypeError(
80
+ `fastify-plugin expects a function, instead got a '${typeof fn}'`
81
+ );
82
+ }
83
+ if (typeof options === "string") {
84
+ options = {
85
+ fastify: options
86
+ };
87
+ }
88
+ if (typeof options !== "object" || Array.isArray(options) || options === null) {
89
+ throw new TypeError("The options object should be an object");
90
+ }
91
+ if (options.fastify !== void 0 && typeof options.fastify !== "string") {
92
+ throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`);
93
+ }
94
+ if (!options.name) {
95
+ autoName = true;
96
+ options.name = getPluginName(fn) + "-auto-" + count++;
97
+ }
98
+ fn[/* @__PURE__ */ Symbol.for("skip-override")] = options.encapsulate !== true;
99
+ fn[/* @__PURE__ */ Symbol.for("fastify.display-name")] = options.name;
100
+ fn[/* @__PURE__ */ Symbol.for("plugin-meta")] = options;
101
+ if (!fn.default) {
102
+ fn.default = fn;
103
+ }
104
+ const camelCase = toCamelCase(options.name);
105
+ if (!autoName && !fn[camelCase]) {
106
+ fn[camelCase] = fn;
107
+ }
108
+ return fn;
109
+ }
110
+ module.exports = plugin;
111
+ module.exports.default = plugin;
112
+ module.exports.fastifyPlugin = plugin;
113
+ }
114
+ });
115
+
116
+ // src/integrations/fastify.ts
117
+ var import_fastify_plugin = __toESM(require_plugin());
118
+ function createTenantContext(manager) {
119
+ const storage = new AsyncLocalStorage();
120
+ function getTenantOrNull() {
121
+ return storage.getStore();
122
+ }
123
+ function getTenant() {
124
+ const context = getTenantOrNull();
125
+ if (!context) {
126
+ throw new Error(
127
+ "[drizzle-multitenant] No tenant context found. Make sure you are calling this within runWithTenant()."
128
+ );
129
+ }
130
+ return context;
131
+ }
132
+ function getTenantId() {
133
+ return getTenant().tenantId;
134
+ }
135
+ function getTenantDb() {
136
+ const tenantId = getTenantId();
137
+ return manager.getDb(tenantId);
138
+ }
139
+ function getSharedDb() {
140
+ return manager.getSharedDb();
141
+ }
142
+ function isInTenantContext() {
143
+ return getTenantOrNull() !== void 0;
144
+ }
145
+ function runWithTenant(context, callback) {
146
+ if (!context.tenantId) {
147
+ throw new Error("[drizzle-multitenant] tenantId is required in context");
148
+ }
149
+ return storage.run(context, callback);
150
+ }
151
+ return {
152
+ runWithTenant,
153
+ getTenant,
154
+ getTenantOrNull,
155
+ getTenantId,
156
+ getTenantDb,
157
+ getSharedDb,
158
+ isInTenantContext
159
+ };
160
+ }
161
+
162
+ // src/integrations/fastify.ts
163
+ var TenantNotFoundError = class extends Error {
164
+ constructor(message = "Tenant not found") {
165
+ super(message);
166
+ this.name = "TenantNotFoundError";
167
+ }
168
+ };
169
+ var TenantValidationError = class extends Error {
170
+ constructor(message = "Tenant validation failed") {
171
+ super(message);
172
+ this.name = "TenantValidationError";
173
+ }
174
+ };
175
+ function createFastifyPlugin(options) {
176
+ const { manager, extractTenantId, validateTenant, enrichContext, onError } = options;
177
+ const tenantContext = createTenantContext(manager);
178
+ const defaultErrorHandler = async (error, _req, reply) => {
179
+ if (error instanceof TenantNotFoundError) {
180
+ reply.status(400).send({ error: "Tenant ID is required" });
181
+ return;
182
+ }
183
+ if (error instanceof TenantValidationError) {
184
+ reply.status(403).send({ error: "Invalid tenant" });
185
+ return;
186
+ }
187
+ reply.status(500).send({ error: "Internal server error" });
188
+ };
189
+ const errorHandler = onError ?? defaultErrorHandler;
190
+ const pluginImpl = async (fastify) => {
191
+ fastify.decorateRequest("tenantContext", void 0);
192
+ fastify.addHook("preHandler", async (req, reply) => {
193
+ let tenantId;
194
+ try {
195
+ tenantId = await extractTenantId(req);
196
+ } catch (error) {
197
+ await errorHandler(error, req, reply);
198
+ throw error;
199
+ }
200
+ if (!tenantId) {
201
+ const error = new TenantNotFoundError("Tenant ID not found in request");
202
+ await errorHandler(error, req, reply);
203
+ throw error;
204
+ }
205
+ if (validateTenant) {
206
+ try {
207
+ const isValid = await validateTenant(tenantId, req);
208
+ if (!isValid) {
209
+ const error = new TenantValidationError(`Tenant ${tenantId} validation failed`);
210
+ await errorHandler(error, req, reply);
211
+ throw error;
212
+ }
213
+ } catch (error) {
214
+ if (!(error instanceof TenantValidationError)) {
215
+ await errorHandler(error, req, reply);
216
+ }
217
+ throw error;
218
+ }
219
+ }
220
+ const customContext = enrichContext ? await enrichContext(tenantId, req) : {};
221
+ const context = {
222
+ tenantId,
223
+ ...customContext
224
+ };
225
+ req.tenantContext = context;
226
+ });
227
+ };
228
+ const plugin = (0, import_fastify_plugin.default)(pluginImpl, {
229
+ name: "drizzle-multitenant"
230
+ });
231
+ return { plugin, context: tenantContext };
232
+ }
233
+
234
+ export { TenantNotFoundError, TenantValidationError, createFastifyPlugin, createTenantContext };
235
+ //# sourceMappingURL=fastify.js.map
236
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../node_modules/fastify-plugin/lib/getPluginName.js","../../node_modules/fastify-plugin/lib/toCamelCase.js","../../node_modules/fastify-plugin/plugin.js","../../src/integrations/fastify.ts","../../src/context.ts"],"names":["exports","fp"],"mappings":"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","file":"fastify.js","sourcesContent":["'use strict'\n\nconst fpStackTracePattern = /at\\s(?:.*\\.)?plugin\\s.*\\n\\s*(.*)/\nconst fileNamePattern = /(\\w*(\\.\\w*)*)\\..*/\n\nmodule.exports = function getPluginName (fn) {\n if (fn.name.length > 0) return fn.name\n\n const stackTraceLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 10\n try {\n throw new Error('anonymous function')\n } catch (e) {\n Error.stackTraceLimit = stackTraceLimit\n return extractPluginName(e.stack)\n }\n}\n\nfunction extractPluginName (stack) {\n const m = stack.match(fpStackTracePattern)\n\n // get last section of path and match for filename\n return m ? m[1].split(/[/\\\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'\n}\nmodule.exports.extractPluginName = extractPluginName\n","'use strict'\n\nmodule.exports = function toCamelCase (name) {\n if (name[0] === '@') {\n name = name.slice(1).replace('/', '-')\n }\n return name.replace(/-(.)/g, function (match, g1) {\n return g1.toUpperCase()\n })\n}\n","'use strict'\n\nconst getPluginName = require('./lib/getPluginName')\nconst toCamelCase = require('./lib/toCamelCase')\n\nlet count = 0\n\nfunction plugin (fn, options = {}) {\n let autoName = false\n\n if (fn.default !== undefined) {\n // Support for 'export default' behaviour in transpiled ECMAScript module\n fn = fn.default\n }\n\n if (typeof fn !== 'function') {\n throw new TypeError(\n `fastify-plugin expects a function, instead got a '${typeof fn}'`\n )\n }\n\n if (typeof options === 'string') {\n options = {\n fastify: options\n }\n }\n\n if (\n typeof options !== 'object' ||\n Array.isArray(options) ||\n options === null\n ) {\n throw new TypeError('The options object should be an object')\n }\n\n if (options.fastify !== undefined && typeof options.fastify !== 'string') {\n throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)\n }\n\n if (!options.name) {\n autoName = true\n options.name = getPluginName(fn) + '-auto-' + count++\n }\n\n fn[Symbol.for('skip-override')] = options.encapsulate !== true\n fn[Symbol.for('fastify.display-name')] = options.name\n fn[Symbol.for('plugin-meta')] = options\n\n // Faux modules support\n if (!fn.default) {\n fn.default = fn\n }\n\n // TypeScript support for named imports\n // See https://github.com/fastify/fastify/issues/2404 for more details\n // The type definitions would have to be update to match this.\n const camelCase = toCamelCase(options.name)\n if (!autoName && !fn[camelCase]) {\n fn[camelCase] = fn\n }\n\n return fn\n}\n\nmodule.exports = plugin\nmodule.exports.default = plugin\nmodule.exports.fastifyPlugin = plugin\n","import type {\n FastifyPluginAsync,\n FastifyRequest,\n FastifyReply,\n FastifyInstance,\n} from 'fastify';\nimport fp from 'fastify-plugin';\nimport type { TenantManager } from '../types.js';\nimport { createTenantContext, type TenantContext, type TenantContextData } from '../context.js';\n\n/**\n * Fastify plugin options\n */\nexport interface FastifyPluginOptions<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Tenant manager instance */\n manager: TenantManager<TTenantSchema, TSharedSchema>;\n\n /**\n * Extract tenant ID from request\n * @example\n * // From header\n * extractTenantId: (req) => req.headers['x-tenant-id'] as string\n *\n * // From path param\n * extractTenantId: (req) => (req.params as any).tenantId\n *\n * // From subdomain\n * extractTenantId: (req) => req.hostname.split('.')[0]\n */\n extractTenantId: (req: FastifyRequest) => string | undefined | Promise<string | undefined>;\n\n /**\n * Optional tenant validation\n * Throw an error or return false to reject the request\n */\n validateTenant?: (tenantId: string, req: FastifyRequest) => boolean | Promise<boolean>;\n\n /**\n * Enrich context with additional data\n */\n enrichContext?: (tenantId: string, req: FastifyRequest) => TCustom | Promise<TCustom>;\n\n /**\n * Custom error handler\n */\n onError?: (error: Error, req: FastifyRequest, reply: FastifyReply) => void | Promise<void>;\n}\n\n/**\n * Tenant not found error\n */\nexport class TenantNotFoundError extends Error {\n constructor(message = 'Tenant not found') {\n super(message);\n this.name = 'TenantNotFoundError';\n }\n}\n\n/**\n * Tenant validation error\n */\nexport class TenantValidationError extends Error {\n constructor(message = 'Tenant validation failed') {\n super(message);\n this.name = 'TenantValidationError';\n }\n}\n\n/**\n * Fastify request decorator\n */\ndeclare module 'fastify' {\n interface FastifyRequest {\n tenantContext?: TenantContextData<Record<string, unknown>>;\n }\n}\n\n/**\n * Create Fastify plugin for tenant context\n *\n * @example\n * ```typescript\n * import Fastify from 'fastify';\n * import { createTenantManager } from 'drizzle-multitenant';\n * import { createFastifyPlugin } from 'drizzle-multitenant/fastify';\n *\n * const fastify = Fastify();\n * const manager = createTenantManager(config);\n *\n * const { plugin, context } = createFastifyPlugin({\n * manager,\n * extractTenantId: (req) => req.headers['x-tenant-id'] as string,\n * });\n *\n * await fastify.register(plugin);\n *\n * fastify.get('/users', async (req, reply) => {\n * const db = context.getTenantDb();\n * const users = await db.select().from(schema.users);\n * return users;\n * });\n * ```\n */\nexport function createFastifyPlugin<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n>(\n options: FastifyPluginOptions<TTenantSchema, TSharedSchema, TCustom>\n): {\n plugin: FastifyPluginAsync;\n context: TenantContext<TTenantSchema, TSharedSchema, TCustom>;\n} {\n const { manager, extractTenantId, validateTenant, enrichContext, onError } = options;\n\n const tenantContext = createTenantContext<TTenantSchema, TSharedSchema, TCustom>(manager);\n\n const defaultErrorHandler = async (\n error: Error,\n _req: FastifyRequest,\n reply: FastifyReply\n ): Promise<void> => {\n if (error instanceof TenantNotFoundError) {\n reply.status(400).send({ error: 'Tenant ID is required' });\n return;\n }\n if (error instanceof TenantValidationError) {\n reply.status(403).send({ error: 'Invalid tenant' });\n return;\n }\n reply.status(500).send({ error: 'Internal server error' });\n };\n\n const errorHandler = onError ?? defaultErrorHandler;\n\n const pluginImpl: FastifyPluginAsync = async (fastify: FastifyInstance): Promise<void> => {\n // Decorate request with tenantContext\n fastify.decorateRequest('tenantContext', undefined);\n\n // Add preHandler hook to set tenant context\n fastify.addHook('preHandler', async (req: FastifyRequest, reply: FastifyReply) => {\n let tenantId: string | undefined;\n\n try {\n tenantId = await extractTenantId(req);\n } catch (error) {\n await errorHandler(error as Error, req, reply);\n throw error; // Re-throw to stop processing\n }\n\n if (!tenantId) {\n const error = new TenantNotFoundError('Tenant ID not found in request');\n await errorHandler(error, req, reply);\n throw error;\n }\n\n if (validateTenant) {\n try {\n const isValid = await validateTenant(tenantId, req);\n if (!isValid) {\n const error = new TenantValidationError(`Tenant ${tenantId} validation failed`);\n await errorHandler(error, req, reply);\n throw error;\n }\n } catch (error) {\n if (!(error instanceof TenantValidationError)) {\n await errorHandler(error as Error, req, reply);\n }\n throw error;\n }\n }\n\n const customContext = enrichContext ? await enrichContext(tenantId, req) : ({} as TCustom);\n\n const context: TenantContextData<TCustom> = {\n tenantId,\n ...customContext,\n };\n\n req.tenantContext = context;\n });\n };\n\n // Use fastify-plugin to make the plugin global (not encapsulated)\n const plugin = fp(pluginImpl, {\n name: 'drizzle-multitenant',\n });\n\n return { plugin, context: tenantContext };\n}\n\n/**\n * Re-export context utilities for convenience\n */\nexport { createTenantContext, type TenantContext, type TenantContextData } from '../context.js';\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { TenantManager, TenantDb, SharedDb } from './types.js';\n\n/**\n * Base tenant context data\n */\nexport interface BaseTenantContext {\n tenantId: string;\n}\n\n/**\n * Tenant context with optional custom data\n */\nexport type TenantContextData<TCustom extends Record<string, unknown> = Record<string, unknown>> =\n BaseTenantContext & TCustom;\n\n/**\n * Tenant context API\n */\nexport interface TenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Run a callback with tenant context\n */\n runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T>;\n\n /**\n * Get current tenant context (throws if not in context)\n */\n getTenant(): TenantContextData<TCustom>;\n\n /**\n * Get current tenant context or undefined\n */\n getTenantOrNull(): TenantContextData<TCustom> | undefined;\n\n /**\n * Get current tenant ID (throws if not in context)\n */\n getTenantId(): string;\n\n /**\n * Get database for current tenant (throws if not in context)\n */\n getTenantDb(): TenantDb<TTenantSchema>;\n\n /**\n * Get shared database\n */\n getSharedDb(): SharedDb<TSharedSchema>;\n\n /**\n * Check if currently running within a tenant context\n */\n isInTenantContext(): boolean;\n}\n\n/**\n * Create a tenant context with AsyncLocalStorage\n *\n * @example\n * ```typescript\n * import { createTenantContext, createTenantManager } from 'drizzle-multitenant';\n *\n * const manager = createTenantManager(config);\n *\n * const {\n * runWithTenant,\n * getTenant,\n * getTenantDb,\n * getSharedDb,\n * } = createTenantContext(manager);\n *\n * // Use in request handler\n * app.get('/users', async (req, res) => {\n * const tenantId = req.headers['x-tenant-id'];\n *\n * await runWithTenant({ tenantId }, async () => {\n * const db = getTenantDb();\n * const users = await db.select().from(schema.users);\n * res.json(users);\n * });\n * });\n * ```\n */\nexport function createTenantContext<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n TCustom extends Record<string, unknown> = Record<string, unknown>,\n>(\n manager: TenantManager<TTenantSchema, TSharedSchema>\n): TenantContext<TTenantSchema, TSharedSchema, TCustom> {\n const storage = new AsyncLocalStorage<TenantContextData<TCustom>>();\n\n function getTenantOrNull(): TenantContextData<TCustom> | undefined {\n return storage.getStore();\n }\n\n function getTenant(): TenantContextData<TCustom> {\n const context = getTenantOrNull();\n if (!context) {\n throw new Error(\n '[drizzle-multitenant] No tenant context found. ' +\n 'Make sure you are calling this within runWithTenant().'\n );\n }\n return context;\n }\n\n function getTenantId(): string {\n return getTenant().tenantId;\n }\n\n function getTenantDb(): TenantDb<TTenantSchema> {\n const tenantId = getTenantId();\n return manager.getDb(tenantId);\n }\n\n function getSharedDb(): SharedDb<TSharedSchema> {\n return manager.getSharedDb();\n }\n\n function isInTenantContext(): boolean {\n return getTenantOrNull() !== undefined;\n }\n\n function runWithTenant<T>(\n context: TenantContextData<TCustom>,\n callback: () => T | Promise<T>\n ): T | Promise<T> {\n if (!context.tenantId) {\n throw new Error('[drizzle-multitenant] tenantId is required in context');\n }\n return storage.run(context, callback);\n }\n\n return {\n runWithTenant,\n getTenant,\n getTenantOrNull,\n getTenantId,\n getTenantDb,\n getSharedDb,\n isInTenantContext,\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=hono.js.map
3
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"hono.js"}
@@ -0,0 +1,386 @@
1
+ import * as _nestjs_common from '@nestjs/common';
2
+ import { ModuleMetadata, Type, InjectionToken, DynamicModule, CanActivate, ExecutionContext, NestInterceptor, CallHandler, Provider } from '@nestjs/common';
3
+ import { Request } from 'express';
4
+ import { C as Config, T as TenantManager } from '../../types-DKVaTaIb.js';
5
+ export { S as SharedDb, a as TenantDb } from '../../types-DKVaTaIb.js';
6
+ import { Reflector } from '@nestjs/core';
7
+ import { Observable } from 'rxjs';
8
+ import 'pg';
9
+ import 'drizzle-orm/node-postgres';
10
+
11
+ /**
12
+ * Function to extract tenant ID from request
13
+ */
14
+ type TenantIdExtractor = (request: Request) => string | undefined | Promise<string | undefined>;
15
+ /**
16
+ * Function to validate tenant ID
17
+ */
18
+ type TenantValidator = (tenantId: string) => boolean | Promise<boolean>;
19
+ /**
20
+ * Tenant context data available in requests
21
+ */
22
+ interface NestTenantContext {
23
+ /** Current tenant ID */
24
+ tenantId: string;
25
+ /** Schema name for the tenant */
26
+ schemaName: string;
27
+ /** Additional custom data */
28
+ [key: string]: unknown;
29
+ }
30
+ /**
31
+ * Options for TenantModule.forRoot()
32
+ */
33
+ interface TenantModuleOptions<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
34
+ /** Drizzle multitenant configuration */
35
+ config: Config<TTenantSchema, TSharedSchema>;
36
+ /** Function to extract tenant ID from request */
37
+ extractTenantId: TenantIdExtractor;
38
+ /** Optional function to validate tenant ID */
39
+ validateTenant?: TenantValidator;
40
+ /** Whether to make the module global */
41
+ isGlobal?: boolean;
42
+ /** Custom context enrichment */
43
+ enrichContext?: (tenantId: string, request: Request) => Record<string, unknown> | Promise<Record<string, unknown>>;
44
+ }
45
+ /**
46
+ * Factory for async options
47
+ */
48
+ interface TenantModuleOptionsFactory<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
49
+ createTenantModuleOptions(): Promise<TenantModuleOptions<TTenantSchema, TSharedSchema>> | TenantModuleOptions<TTenantSchema, TSharedSchema>;
50
+ }
51
+ /**
52
+ * Options for TenantModule.forRootAsync()
53
+ */
54
+ interface TenantModuleAsyncOptions<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> extends Pick<ModuleMetadata, 'imports'> {
55
+ /** Whether to make the module global */
56
+ isGlobal?: boolean;
57
+ /** Use existing provider */
58
+ useExisting?: Type<TenantModuleOptionsFactory<TTenantSchema, TSharedSchema>>;
59
+ /** Use class as factory */
60
+ useClass?: Type<TenantModuleOptionsFactory<TTenantSchema, TSharedSchema>>;
61
+ /** Use factory function */
62
+ useFactory?: (...args: unknown[]) => Promise<TenantModuleOptions<TTenantSchema, TSharedSchema>> | TenantModuleOptions<TTenantSchema, TSharedSchema>;
63
+ /** Dependencies to inject into factory */
64
+ inject?: InjectionToken[];
65
+ }
66
+ /**
67
+ * Extended request with tenant context
68
+ */
69
+ interface TenantRequest extends Request {
70
+ tenantContext?: NestTenantContext;
71
+ tenantId?: string;
72
+ }
73
+
74
+ /**
75
+ * NestJS module for multi-tenant support
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Basic usage
80
+ * @Module({
81
+ * imports: [
82
+ * TenantModule.forRoot({
83
+ * config: tenantConfig,
84
+ * extractTenantId: (req) => req.headers['x-tenant-id'] as string,
85
+ * isGlobal: true,
86
+ * }),
87
+ * ],
88
+ * })
89
+ * export class AppModule {}
90
+ *
91
+ * // Async usage with ConfigService
92
+ * @Module({
93
+ * imports: [
94
+ * TenantModule.forRootAsync({
95
+ * imports: [ConfigModule],
96
+ * useFactory: (configService: ConfigService) => ({
97
+ * config: defineConfig({
98
+ * connection: { url: configService.get('DATABASE_URL') },
99
+ * isolation: {
100
+ * strategy: 'schema',
101
+ * schemaNameTemplate: (id) => `tenant_${id}`,
102
+ * },
103
+ * schemas: { tenant: tenantSchema },
104
+ * }),
105
+ * extractTenantId: (req) => req.params.tenantId,
106
+ * }),
107
+ * inject: [ConfigService],
108
+ * isGlobal: true,
109
+ * }),
110
+ * ],
111
+ * })
112
+ * export class AppModule {}
113
+ * ```
114
+ */
115
+ declare class TenantModule {
116
+ /**
117
+ * Register the module with static configuration
118
+ */
119
+ static forRoot<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>>(options: TenantModuleOptions<TTenantSchema, TSharedSchema>): DynamicModule;
120
+ /**
121
+ * Register the module with async configuration
122
+ */
123
+ static forRootAsync<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>>(options: TenantModuleAsyncOptions<TTenantSchema, TSharedSchema>): DynamicModule;
124
+ }
125
+ /**
126
+ * Alias for TenantModule for those who prefer this naming
127
+ */
128
+ declare const DrizzleMultitenantModule: typeof TenantModule;
129
+
130
+ /**
131
+ * Inject the tenant database for the current request
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * @Injectable()
136
+ * export class UserService {
137
+ * constructor(@InjectTenantDb() private readonly db: TenantDb) {}
138
+ *
139
+ * async findAll() {
140
+ * return this.db.select().from(users);
141
+ * }
142
+ * }
143
+ * ```
144
+ */
145
+ declare const InjectTenantDb: () => ParameterDecorator;
146
+ /**
147
+ * Inject the shared database
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * @Injectable()
152
+ * export class PlanService {
153
+ * constructor(@InjectSharedDb() private readonly db: SharedDb) {}
154
+ *
155
+ * async findAll() {
156
+ * return this.db.select().from(plans);
157
+ * }
158
+ * }
159
+ * ```
160
+ */
161
+ declare const InjectSharedDb: () => ParameterDecorator;
162
+ /**
163
+ * Inject the tenant context
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * @Injectable()
168
+ * export class AuditService {
169
+ * constructor(@InjectTenantContext() private readonly ctx: NestTenantContext) {}
170
+ *
171
+ * log(action: string) {
172
+ * console.log(`[${this.ctx.tenantId}] ${action}`);
173
+ * }
174
+ * }
175
+ * ```
176
+ */
177
+ declare const InjectTenantContext: () => ParameterDecorator;
178
+ /**
179
+ * Inject the tenant manager
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * @Injectable()
184
+ * export class TenantService {
185
+ * constructor(@InjectTenantManager() private readonly manager: TenantManager) {}
186
+ *
187
+ * getPoolCount() {
188
+ * return this.manager.getPoolCount();
189
+ * }
190
+ * }
191
+ * ```
192
+ */
193
+ declare const InjectTenantManager: () => ParameterDecorator;
194
+ /**
195
+ * Get the current tenant context from the request
196
+ * Use this in controllers to access tenant information
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * @Controller('users')
201
+ * export class UserController {
202
+ * @Get()
203
+ * findAll(@TenantCtx() ctx: NestTenantContext) {
204
+ * console.log(`Fetching users for tenant: ${ctx.tenantId}`);
205
+ * return this.userService.findAll();
206
+ * }
207
+ * }
208
+ * ```
209
+ */
210
+ declare const TenantCtx: (...dataOrPipes: (keyof NestTenantContext | _nestjs_common.PipeTransform<any, any> | _nestjs_common.Type<_nestjs_common.PipeTransform<any, any>> | undefined)[]) => ParameterDecorator;
211
+ /**
212
+ * Get the current tenant ID from the request
213
+ * Shorthand for @TenantCtx('tenantId')
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * @Controller('users')
218
+ * export class UserController {
219
+ * @Get()
220
+ * findAll(@TenantId() tenantId: string) {
221
+ * console.log(`Fetching users for tenant: ${tenantId}`);
222
+ * return this.userService.findAll();
223
+ * }
224
+ * }
225
+ * ```
226
+ */
227
+ declare const TenantId: (...dataOrPipes: unknown[]) => ParameterDecorator;
228
+ /**
229
+ * Mark a route as requiring a tenant context
230
+ * Used with TenantGuard to enforce tenant requirement
231
+ *
232
+ * @example
233
+ * ```typescript
234
+ * @Controller('users')
235
+ * @RequiresTenant()
236
+ * export class UserController {
237
+ * // All routes in this controller require a tenant
238
+ * }
239
+ * ```
240
+ */
241
+ declare const RequiresTenant: () => ClassDecorator & MethodDecorator;
242
+ /**
243
+ * Mark a route as public (no tenant required)
244
+ * Use this to exclude specific routes from tenant requirement
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * @Controller('health')
249
+ * export class HealthController {
250
+ * @Get()
251
+ * @PublicRoute()
252
+ * check() {
253
+ * return { status: 'ok' };
254
+ * }
255
+ * }
256
+ * ```
257
+ */
258
+ declare const PublicRoute: () => MethodDecorator;
259
+
260
+ /**
261
+ * Guard that extracts and validates tenant ID from requests
262
+ *
263
+ * This guard should be applied globally or to specific controllers/routes
264
+ * that require tenant context.
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * // Apply globally in main.ts
269
+ * const app = await NestFactory.create(AppModule);
270
+ * app.useGlobalGuards(app.get(TenantGuard));
271
+ *
272
+ * // Or apply to specific controllers
273
+ * @Controller('users')
274
+ * @UseGuards(TenantGuard)
275
+ * export class UserController {}
276
+ * ```
277
+ */
278
+ declare class TenantGuard implements CanActivate {
279
+ private readonly reflector;
280
+ private readonly options;
281
+ private readonly tenantManager;
282
+ constructor(reflector: Reflector, options: TenantModuleOptions, tenantManager: TenantManager);
283
+ canActivate(context: ExecutionContext): Promise<boolean>;
284
+ }
285
+ /**
286
+ * Guard that requires a valid tenant context
287
+ * Throws error if tenant is not present
288
+ *
289
+ * Use this when you want to ensure a route always has a tenant,
290
+ * regardless of the @RequiresTenant decorator.
291
+ *
292
+ * @example
293
+ * ```typescript
294
+ * @Controller('users')
295
+ * @UseGuards(RequireTenantGuard)
296
+ * export class UserController {
297
+ * // All routes require tenant
298
+ * }
299
+ * ```
300
+ */
301
+ declare class RequireTenantGuard implements CanActivate {
302
+ private readonly options;
303
+ constructor(options: TenantModuleOptions);
304
+ canActivate(context: ExecutionContext): Promise<boolean>;
305
+ }
306
+
307
+ /**
308
+ * Interceptor that sets up AsyncLocalStorage context for tenant
309
+ *
310
+ * This interceptor ensures that tenant context is available via
311
+ * AsyncLocalStorage throughout the request lifecycle, enabling
312
+ * access to tenant info in services that don't have request scope.
313
+ *
314
+ * @example
315
+ * ```typescript
316
+ * // Apply globally
317
+ * const app = await NestFactory.create(AppModule);
318
+ * app.useGlobalInterceptors(app.get(TenantContextInterceptor));
319
+ *
320
+ * // Or apply to specific controllers
321
+ * @Controller('users')
322
+ * @UseInterceptors(TenantContextInterceptor)
323
+ * export class UserController {}
324
+ * ```
325
+ */
326
+ declare class TenantContextInterceptor implements NestInterceptor {
327
+ private readonly tenantManager;
328
+ private readonly tenantContext;
329
+ constructor(tenantManager: TenantManager);
330
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
331
+ }
332
+ /**
333
+ * Interceptor that logs tenant information for each request
334
+ *
335
+ * Useful for debugging and audit purposes.
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * @Controller('users')
340
+ * @UseInterceptors(TenantLoggingInterceptor)
341
+ * export class UserController {}
342
+ * ```
343
+ */
344
+ declare class TenantLoggingInterceptor implements NestInterceptor {
345
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
346
+ }
347
+
348
+ /**
349
+ * Create providers for the tenant module
350
+ */
351
+ declare function createTenantProviders<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>>(): Provider[];
352
+ /**
353
+ * Create async providers for dynamic module configuration
354
+ */
355
+ declare function createAsyncProviders<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>>(options: {
356
+ useFactory?: (...args: unknown[]) => Promise<TenantModuleOptions<TTenantSchema, TSharedSchema>> | TenantModuleOptions<TTenantSchema, TSharedSchema>;
357
+ inject?: InjectionToken[];
358
+ useClass?: new (...args: unknown[]) => {
359
+ createTenantModuleOptions(): Promise<TenantModuleOptions<TTenantSchema, TSharedSchema>> | TenantModuleOptions<TTenantSchema, TSharedSchema>;
360
+ };
361
+ useExisting?: new (...args: unknown[]) => {
362
+ createTenantModuleOptions(): Promise<TenantModuleOptions<TTenantSchema, TSharedSchema>> | TenantModuleOptions<TTenantSchema, TSharedSchema>;
363
+ };
364
+ }): Provider[];
365
+
366
+ /**
367
+ * Injection tokens for NestJS
368
+ */
369
+ /** Token for injecting the TenantManager */
370
+ declare const TENANT_MANAGER: unique symbol;
371
+ /** Token for injecting the tenant database */
372
+ declare const TENANT_DB: unique symbol;
373
+ /** Token for injecting the shared database */
374
+ declare const SHARED_DB: unique symbol;
375
+ /** Token for injecting the tenant context */
376
+ declare const TENANT_CONTEXT: unique symbol;
377
+ /** Token for the module configuration */
378
+ declare const TENANT_MODULE_OPTIONS: unique symbol;
379
+ /** Token for the tenant ID extractor function */
380
+ declare const TENANT_ID_EXTRACTOR: unique symbol;
381
+ /** Metadata key for tenant requirement */
382
+ declare const REQUIRES_TENANT_KEY = "requires_tenant";
383
+ /** Metadata key for public routes (no tenant required) */
384
+ declare const IS_PUBLIC_KEY = "is_public_tenant";
385
+
386
+ export { Config, DrizzleMultitenantModule, IS_PUBLIC_KEY, InjectSharedDb, InjectTenantContext, InjectTenantDb, InjectTenantManager, type NestTenantContext, PublicRoute, REQUIRES_TENANT_KEY, RequireTenantGuard, RequiresTenant, SHARED_DB, TENANT_CONTEXT, TENANT_DB, TENANT_ID_EXTRACTOR, TENANT_MANAGER, TENANT_MODULE_OPTIONS, TenantContextInterceptor, TenantCtx, TenantGuard, TenantId, type TenantIdExtractor, TenantLoggingInterceptor, TenantManager, TenantModule, type TenantModuleAsyncOptions, type TenantModuleOptions, type TenantModuleOptionsFactory, type TenantRequest, type TenantValidator, createAsyncProviders, createTenantProviders };