drizzle-multitenant 1.0.7 → 1.0.9
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 +1 -1
- package/README.md +36 -372
- package/dist/cli/index.js +686 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/{context-DBerWr50.d.ts → context-DoHx79MS.d.ts} +1 -1
- package/dist/cross-schema/index.d.ts +152 -1
- package/dist/cross-schema/index.js +208 -1
- package/dist/cross-schema/index.js.map +1 -1
- package/dist/index.d.ts +62 -5
- package/dist/index.js +1181 -50
- package/dist/index.js.map +1 -1
- package/dist/integrations/express.d.ts +3 -3
- package/dist/integrations/fastify.d.ts +3 -3
- package/dist/integrations/nestjs/index.d.ts +1 -1
- package/dist/integrations/nestjs/index.js +484 -3
- package/dist/integrations/nestjs/index.js.map +1 -1
- package/dist/migrator/index.d.ts +116 -1
- package/dist/migrator/index.js +418 -0
- package/dist/migrator/index.js.map +1 -1
- package/dist/types-B5eSRLFW.d.ts +235 -0
- package/package.json +9 -3
- package/.claude/settings.local.json +0 -20
- package/dist/types-DKVaTaIb.d.ts +0 -130
- package/proposals/improvements.md +0 -383
- package/roadmap.md +0 -921
|
@@ -101,6 +101,30 @@ type ColumnSelection<T extends Table> = {
|
|
|
101
101
|
type InferSelectedColumns<T extends Table, TSelection extends ColumnSelection<T>> = {
|
|
102
102
|
[K in keyof TSelection as TSelection[K] extends true ? K : never]: T['_']['columns'][K extends keyof T['_']['columns'] ? K : never]['_']['data'];
|
|
103
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Configuration for withShared helper
|
|
106
|
+
*/
|
|
107
|
+
interface WithSharedConfig<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
108
|
+
/** Tenant schema object containing table definitions */
|
|
109
|
+
tenant: TTenantSchema;
|
|
110
|
+
/** Shared schema object containing table definitions */
|
|
111
|
+
shared: TSharedSchema;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Options for withShared helper
|
|
115
|
+
*/
|
|
116
|
+
interface WithSharedOptions {
|
|
117
|
+
/** Tenant schema name (default: derived from tenantDb) */
|
|
118
|
+
tenantSchema?: string;
|
|
119
|
+
/** Shared schema name (default: 'public') */
|
|
120
|
+
sharedSchema?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Infer result type from select fields
|
|
124
|
+
*/
|
|
125
|
+
type InferSelectResult<T extends Record<string, Column>> = {
|
|
126
|
+
[K in keyof T]: T[K]['_']['data'];
|
|
127
|
+
};
|
|
104
128
|
|
|
105
129
|
/**
|
|
106
130
|
* Cross-schema query builder for joining tenant and shared data
|
|
@@ -259,4 +283,131 @@ declare function buildCrossSchemaSelect<T extends Record<string, Column>>(fields
|
|
|
259
283
|
getSchema: () => string;
|
|
260
284
|
};
|
|
261
285
|
|
|
262
|
-
|
|
286
|
+
/**
|
|
287
|
+
* Simplified cross-schema query builder with automatic schema detection
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const result = await withShared(tenantDb, sharedDb, { tenant: tenantSchema, shared: sharedSchema })
|
|
292
|
+
* .from(pedidos)
|
|
293
|
+
* .leftJoin(workflowSteps, eq(pedidos.workflowStepId, workflowSteps.id))
|
|
294
|
+
* .select({ pedidoId: pedidos.id, workflowNome: workflowSteps.nome })
|
|
295
|
+
* .execute();
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
declare class WithSharedQueryBuilder<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, _TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
299
|
+
private readonly tenantDb;
|
|
300
|
+
private readonly sharedTables;
|
|
301
|
+
private readonly tenantSchemaName;
|
|
302
|
+
private readonly sharedSchemaName;
|
|
303
|
+
private fromTable;
|
|
304
|
+
private joins;
|
|
305
|
+
private selectFields;
|
|
306
|
+
private whereCondition;
|
|
307
|
+
private orderByFields;
|
|
308
|
+
private limitValue;
|
|
309
|
+
private offsetValue;
|
|
310
|
+
constructor(tenantDb: NodePgDatabase<TTenantSchema>, sharedTables: Set<Table>, tenantSchemaName: string, sharedSchemaName?: string);
|
|
311
|
+
/**
|
|
312
|
+
* Set the main table to query from
|
|
313
|
+
* Automatically detects if it's a tenant or shared table
|
|
314
|
+
*/
|
|
315
|
+
from<T extends Table>(table: T): this;
|
|
316
|
+
/**
|
|
317
|
+
* Add a left join with automatic schema detection
|
|
318
|
+
*/
|
|
319
|
+
leftJoin<T extends Table>(table: T, condition: JoinCondition): this;
|
|
320
|
+
/**
|
|
321
|
+
* Add an inner join with automatic schema detection
|
|
322
|
+
*/
|
|
323
|
+
innerJoin<T extends Table>(table: T, condition: JoinCondition): this;
|
|
324
|
+
/**
|
|
325
|
+
* Add a right join with automatic schema detection
|
|
326
|
+
*/
|
|
327
|
+
rightJoin<T extends Table>(table: T, condition: JoinCondition): this;
|
|
328
|
+
/**
|
|
329
|
+
* Add a full outer join with automatic schema detection
|
|
330
|
+
*/
|
|
331
|
+
fullJoin<T extends Table>(table: T, condition: JoinCondition): this;
|
|
332
|
+
/**
|
|
333
|
+
* Select specific fields
|
|
334
|
+
*/
|
|
335
|
+
select<T extends Record<string, Column>>(fields: T): this;
|
|
336
|
+
/**
|
|
337
|
+
* Add a WHERE condition
|
|
338
|
+
*/
|
|
339
|
+
where(condition: SQL<unknown>): this;
|
|
340
|
+
/**
|
|
341
|
+
* Add ORDER BY
|
|
342
|
+
*/
|
|
343
|
+
orderBy(...fields: SQL<unknown>[]): this;
|
|
344
|
+
/**
|
|
345
|
+
* Set LIMIT
|
|
346
|
+
*/
|
|
347
|
+
limit(value: number): this;
|
|
348
|
+
/**
|
|
349
|
+
* Set OFFSET
|
|
350
|
+
*/
|
|
351
|
+
offset(value: number): this;
|
|
352
|
+
/**
|
|
353
|
+
* Execute the query and return typed results
|
|
354
|
+
*/
|
|
355
|
+
execute<TResult extends Record<string, unknown> = InferSelectResult<typeof this.selectFields>>(): Promise<TResult[]>;
|
|
356
|
+
/**
|
|
357
|
+
* Add a join to the query
|
|
358
|
+
*/
|
|
359
|
+
private addJoin;
|
|
360
|
+
/**
|
|
361
|
+
* Build the SQL query
|
|
362
|
+
*/
|
|
363
|
+
private buildSql;
|
|
364
|
+
/**
|
|
365
|
+
* Get table alias for a column (used in SELECT)
|
|
366
|
+
*/
|
|
367
|
+
private getTableAliasForColumn;
|
|
368
|
+
/**
|
|
369
|
+
* Get SQL keyword for join type
|
|
370
|
+
*/
|
|
371
|
+
private getJoinKeyword;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Create a simplified cross-schema query builder with automatic schema detection
|
|
375
|
+
*
|
|
376
|
+
* This helper automatically detects whether a table belongs to the tenant schema
|
|
377
|
+
* or the shared schema based on the schema configuration provided.
|
|
378
|
+
*
|
|
379
|
+
* @param tenantDb - The tenant database instance
|
|
380
|
+
* @param sharedDb - The shared database instance (unused but kept for API symmetry)
|
|
381
|
+
* @param schemas - Object containing tenant and shared schema definitions
|
|
382
|
+
* @param options - Optional configuration for schema names
|
|
383
|
+
* @returns A query builder with automatic schema detection
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```typescript
|
|
387
|
+
* // Define your schemas
|
|
388
|
+
* const tenantSchema = { pedidos, clientes };
|
|
389
|
+
* const sharedSchema = { workflowSteps, plans };
|
|
390
|
+
*
|
|
391
|
+
* // Use withShared for cross-schema queries
|
|
392
|
+
* const result = await withShared(
|
|
393
|
+
* tenantDb,
|
|
394
|
+
* sharedDb,
|
|
395
|
+
* { tenant: tenantSchema, shared: sharedSchema }
|
|
396
|
+
* )
|
|
397
|
+
* .from(pedidos) // Auto-detected as tenant table
|
|
398
|
+
* .leftJoin(workflowSteps, // Auto-detected as shared table
|
|
399
|
+
* eq(pedidos.workflowStepId, workflowSteps.id)
|
|
400
|
+
* )
|
|
401
|
+
* .select({
|
|
402
|
+
* pedidoId: pedidos.id,
|
|
403
|
+
* workflowNome: workflowSteps.nome,
|
|
404
|
+
* })
|
|
405
|
+
* .where(eq(pedidos.status, 'active'))
|
|
406
|
+
* .orderBy(desc(pedidos.createdAt))
|
|
407
|
+
* .limit(10)
|
|
408
|
+
* .execute();
|
|
409
|
+
* ```
|
|
410
|
+
*/
|
|
411
|
+
declare function withShared<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>>(tenantDb: NodePgDatabase<TTenantSchema>, _sharedDb: NodePgDatabase<TSharedSchema>, schemas: WithSharedConfig<TTenantSchema, TSharedSchema>, options?: WithSharedOptions): WithSharedQueryBuilder<TTenantSchema, TSharedSchema>;
|
|
412
|
+
|
|
413
|
+
export { type ColumnSelection, type CrossSchemaContext, CrossSchemaQueryBuilder, type CrossSchemaRawOptions, type InferSelectResult, type InferSelectedColumns, type JoinCondition, type JoinDefinition, type JoinType, type LookupResult, type QueryBuilderState, type SchemaSource, type SelectField, type SharedLookupConfig, type TableReference, type WithSharedConfig, type WithSharedOptions, WithSharedQueryBuilder, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withShared, withSharedLookup };
|
|
@@ -213,7 +213,214 @@ function buildCrossSchemaSelect(fields, tenantSchema, _sharedSchema) {
|
|
|
213
213
|
};
|
|
214
214
|
return { columns, getSchema };
|
|
215
215
|
}
|
|
216
|
+
function extractTablesFromSchema(schema) {
|
|
217
|
+
const tables = /* @__PURE__ */ new Set();
|
|
218
|
+
for (const value of Object.values(schema)) {
|
|
219
|
+
if (value && typeof value === "object" && "_" in value) {
|
|
220
|
+
const branded = value;
|
|
221
|
+
if (branded._?.brand === "Table") {
|
|
222
|
+
tables.add(value);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return tables;
|
|
227
|
+
}
|
|
228
|
+
function isSharedTable(table, sharedTables) {
|
|
229
|
+
return sharedTables.has(table);
|
|
230
|
+
}
|
|
231
|
+
var WithSharedQueryBuilder = class {
|
|
232
|
+
constructor(tenantDb, sharedTables, tenantSchemaName, sharedSchemaName = "public") {
|
|
233
|
+
this.tenantDb = tenantDb;
|
|
234
|
+
this.sharedTables = sharedTables;
|
|
235
|
+
this.tenantSchemaName = tenantSchemaName;
|
|
236
|
+
this.sharedSchemaName = sharedSchemaName;
|
|
237
|
+
}
|
|
238
|
+
fromTable = null;
|
|
239
|
+
joins = [];
|
|
240
|
+
selectFields = {};
|
|
241
|
+
whereCondition = null;
|
|
242
|
+
orderByFields = [];
|
|
243
|
+
limitValue = null;
|
|
244
|
+
offsetValue = null;
|
|
245
|
+
/**
|
|
246
|
+
* Set the main table to query from
|
|
247
|
+
* Automatically detects if it's a tenant or shared table
|
|
248
|
+
*/
|
|
249
|
+
from(table) {
|
|
250
|
+
const isShared = isSharedTable(table, this.sharedTables);
|
|
251
|
+
this.fromTable = {
|
|
252
|
+
table,
|
|
253
|
+
isShared,
|
|
254
|
+
schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName
|
|
255
|
+
};
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Add a left join with automatic schema detection
|
|
260
|
+
*/
|
|
261
|
+
leftJoin(table, condition) {
|
|
262
|
+
return this.addJoin(table, condition, "left");
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Add an inner join with automatic schema detection
|
|
266
|
+
*/
|
|
267
|
+
innerJoin(table, condition) {
|
|
268
|
+
return this.addJoin(table, condition, "inner");
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Add a right join with automatic schema detection
|
|
272
|
+
*/
|
|
273
|
+
rightJoin(table, condition) {
|
|
274
|
+
return this.addJoin(table, condition, "right");
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Add a full outer join with automatic schema detection
|
|
278
|
+
*/
|
|
279
|
+
fullJoin(table, condition) {
|
|
280
|
+
return this.addJoin(table, condition, "full");
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Select specific fields
|
|
284
|
+
*/
|
|
285
|
+
select(fields) {
|
|
286
|
+
this.selectFields = fields;
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Add a WHERE condition
|
|
291
|
+
*/
|
|
292
|
+
where(condition) {
|
|
293
|
+
this.whereCondition = condition;
|
|
294
|
+
return this;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Add ORDER BY
|
|
298
|
+
*/
|
|
299
|
+
orderBy(...fields) {
|
|
300
|
+
this.orderByFields = fields;
|
|
301
|
+
return this;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Set LIMIT
|
|
305
|
+
*/
|
|
306
|
+
limit(value) {
|
|
307
|
+
this.limitValue = value;
|
|
308
|
+
return this;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Set OFFSET
|
|
312
|
+
*/
|
|
313
|
+
offset(value) {
|
|
314
|
+
this.offsetValue = value;
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Execute the query and return typed results
|
|
319
|
+
*/
|
|
320
|
+
async execute() {
|
|
321
|
+
if (!this.fromTable) {
|
|
322
|
+
throw new Error("[drizzle-multitenant] No table specified. Use .from() first.");
|
|
323
|
+
}
|
|
324
|
+
const sqlQuery = this.buildSql();
|
|
325
|
+
const result = await this.tenantDb.execute(sqlQuery);
|
|
326
|
+
return result.rows;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Add a join to the query
|
|
330
|
+
*/
|
|
331
|
+
addJoin(table, condition, type) {
|
|
332
|
+
const isShared = isSharedTable(table, this.sharedTables);
|
|
333
|
+
this.joins.push({
|
|
334
|
+
table,
|
|
335
|
+
isShared,
|
|
336
|
+
schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,
|
|
337
|
+
condition,
|
|
338
|
+
type
|
|
339
|
+
});
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Build the SQL query
|
|
344
|
+
*/
|
|
345
|
+
buildSql() {
|
|
346
|
+
if (!this.fromTable) {
|
|
347
|
+
throw new Error("[drizzle-multitenant] No table specified");
|
|
348
|
+
}
|
|
349
|
+
const parts = [];
|
|
350
|
+
const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {
|
|
351
|
+
const columnName = column.name;
|
|
352
|
+
const tableName = this.getTableAliasForColumn(column);
|
|
353
|
+
if (tableName) {
|
|
354
|
+
return sql`${sql.raw(`"${tableName}"."${columnName}"`)} as ${sql.raw(`"${alias}"`)}`;
|
|
355
|
+
}
|
|
356
|
+
return sql`${sql.raw(`"${columnName}"`)} as ${sql.raw(`"${alias}"`)}`;
|
|
357
|
+
});
|
|
358
|
+
if (selectParts.length === 0) {
|
|
359
|
+
parts.push(sql`SELECT *`);
|
|
360
|
+
} else {
|
|
361
|
+
parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);
|
|
362
|
+
}
|
|
363
|
+
const fromTableName = getTableName(this.fromTable.table);
|
|
364
|
+
const fromTableRef = `"${this.fromTable.schemaName}"."${fromTableName}"`;
|
|
365
|
+
parts.push(sql` FROM ${sql.raw(fromTableRef)} "${sql.raw(fromTableName)}"`);
|
|
366
|
+
for (const join of this.joins) {
|
|
367
|
+
const joinTableName = getTableName(join.table);
|
|
368
|
+
const joinTableRef = `"${join.schemaName}"."${joinTableName}"`;
|
|
369
|
+
const joinKeyword = this.getJoinKeyword(join.type);
|
|
370
|
+
parts.push(
|
|
371
|
+
sql` ${sql.raw(joinKeyword)} ${sql.raw(joinTableRef)} "${sql.raw(joinTableName)}" ON ${join.condition}`
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
if (this.whereCondition) {
|
|
375
|
+
parts.push(sql` WHERE ${this.whereCondition}`);
|
|
376
|
+
}
|
|
377
|
+
if (this.orderByFields.length > 0) {
|
|
378
|
+
parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);
|
|
379
|
+
}
|
|
380
|
+
if (this.limitValue !== null) {
|
|
381
|
+
parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);
|
|
382
|
+
}
|
|
383
|
+
if (this.offsetValue !== null) {
|
|
384
|
+
parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);
|
|
385
|
+
}
|
|
386
|
+
return sql.join(parts, sql``);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get table alias for a column (used in SELECT)
|
|
390
|
+
*/
|
|
391
|
+
getTableAliasForColumn(column) {
|
|
392
|
+
const columnTable = column.table;
|
|
393
|
+
if (columnTable) {
|
|
394
|
+
return getTableName(columnTable);
|
|
395
|
+
}
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Get SQL keyword for join type
|
|
400
|
+
*/
|
|
401
|
+
getJoinKeyword(type) {
|
|
402
|
+
switch (type) {
|
|
403
|
+
case "inner":
|
|
404
|
+
return "INNER JOIN";
|
|
405
|
+
case "left":
|
|
406
|
+
return "LEFT JOIN";
|
|
407
|
+
case "right":
|
|
408
|
+
return "RIGHT JOIN";
|
|
409
|
+
case "full":
|
|
410
|
+
return "FULL OUTER JOIN";
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
function withShared(tenantDb, _sharedDb, schemas, options) {
|
|
415
|
+
const sharedTables = extractTablesFromSchema(schemas.shared);
|
|
416
|
+
return new WithSharedQueryBuilder(
|
|
417
|
+
tenantDb,
|
|
418
|
+
sharedTables,
|
|
419
|
+
options?.tenantSchema ?? "tenant",
|
|
420
|
+
options?.sharedSchema ?? "public"
|
|
421
|
+
);
|
|
422
|
+
}
|
|
216
423
|
|
|
217
|
-
export { CrossSchemaQueryBuilder, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withSharedLookup };
|
|
424
|
+
export { CrossSchemaQueryBuilder, WithSharedQueryBuilder, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withShared, withSharedLookup };
|
|
218
425
|
//# sourceMappingURL=index.js.map
|
|
219
426
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cross-schema/cross-schema.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Table, Column } from 'drizzle-orm';\nimport type {\n CrossSchemaContext,\n SchemaSource,\n JoinType,\n JoinCondition,\n SharedLookupConfig,\n CrossSchemaRawOptions,\n} from './types.js';\n\n/**\n * Cross-schema query builder for joining tenant and shared data\n *\n * @example\n * ```typescript\n * const query = createCrossSchemaQuery({\n * tenantDb: tenants.getDb('tenant-uuid'),\n * sharedDb: tenants.getSharedDb(),\n * });\n *\n * const results = await query\n * .from('tenant', orders)\n * .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))\n * .select({\n * orderId: orders.id,\n * planName: subscriptionPlans.name,\n * })\n * .execute();\n * ```\n */\nexport class CrossSchemaQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: { table: Table; source: SchemaSource; schemaName: string } | null = null;\n private joins: Array<{\n table: Table;\n source: SchemaSource;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(private readonly context: CrossSchemaContext<TTenantSchema, TSharedSchema>) {}\n\n /**\n * Set the main table to query from\n */\n from<T extends Table>(source: SchemaSource, table: T): this {\n const schemaName = this.getSchemaName(source);\n this.fromTable = { table, source, schemaName };\n return this;\n }\n\n /**\n * Add an inner join\n */\n innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'inner');\n }\n\n /**\n * Add a left join\n */\n leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'left');\n }\n\n /**\n * Add a right join\n */\n rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'right');\n }\n\n /**\n * Add a full outer join\n */\n fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a where condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add order by\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set limit\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set offset\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult = Record<string, unknown>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n\n // Use the tenant db to execute (it has access to both schemas via search_path)\n const result = await this.context.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause\n const fromTableRef = this.getFullTableName(this.fromTable.schemaName, this.fromTable.table);\n parts.push(sql` FROM ${sql.raw(fromTableRef)}`);\n\n // JOIN clauses\n for (const join of this.joins) {\n const joinTableRef = this.getFullTableName(join.schemaName, join.table);\n const joinType = this.getJoinKeyword(join.type);\n parts.push(sql` ${sql.raw(joinType)} ${sql.raw(joinTableRef)} ON ${join.condition}`);\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n source: SchemaSource,\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const schemaName = this.getSchemaName(source);\n this.joins.push({ table, source, schemaName, condition, type });\n return this;\n }\n\n /**\n * Get schema name for a source\n */\n private getSchemaName(source: SchemaSource): string {\n if (source === 'tenant') {\n return this.context.tenantSchema ?? 'tenant';\n }\n return this.context.sharedSchema ?? 'public';\n }\n\n /**\n * Get fully qualified table name\n */\n private getFullTableName(schemaName: string, table: Table): string {\n const tableName = getTableName(table);\n return `\"${schemaName}\".\"${tableName}\"`;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a cross-schema query builder\n */\nexport function createCrossSchemaQuery<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n context: CrossSchemaContext<TTenantSchema, TSharedSchema>\n): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema> {\n return new CrossSchemaQueryBuilder(context);\n}\n\n/**\n * Helper for common pattern: tenant table with shared lookup\n *\n * @example\n * ```typescript\n * const ordersWithPlans = await withSharedLookup({\n * tenantDb,\n * sharedDb,\n * tenantTable: orders,\n * sharedTable: subscriptionPlans,\n * foreignKey: 'planId',\n * sharedFields: ['name', 'features', 'price'],\n * });\n * ```\n */\nexport async function withSharedLookup<\n TTenantTable extends Table,\n TSharedTable extends Table,\n TSharedFields extends keyof TSharedTable['_']['columns'],\n>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>> {\n const {\n tenantDb,\n tenantTable,\n sharedTable,\n foreignKey,\n sharedKey = 'id' as keyof TSharedTable['_']['columns'],\n sharedFields,\n where: whereCondition,\n } = config;\n\n // Get table names using Drizzle's utility\n const tenantTableName = getTableName(tenantTable);\n const sharedTableName = getTableName(sharedTable);\n\n // Build field list for shared table\n const sharedFieldList = sharedFields\n .map((field) => `s.\"${String(field)}\"`)\n .join(', ');\n\n // Build the query\n const queryParts = [\n `SELECT t.*, ${sharedFieldList}`,\n `FROM \"${tenantTableName}\" t`,\n `LEFT JOIN \"public\".\"${sharedTableName}\" s ON t.\"${String(foreignKey)}\" = s.\"${String(sharedKey)}\"`,\n ];\n\n if (whereCondition) {\n queryParts.push('WHERE');\n // We'll need to use raw SQL for the where condition\n }\n\n const sqlQuery = sql.raw(queryParts.join(' '));\n\n const result = await tenantDb.execute(sqlQuery);\n\n return result.rows as Array<Record<string, unknown>>;\n}\n\n/**\n * Execute raw cross-schema SQL with type safety\n *\n * @example\n * ```typescript\n * const result = await crossSchemaRaw<{ userName: string; planName: string }>({\n * tenantSchema: 'tenant_abc123',\n * sharedSchema: 'public',\n * sql: `\n * SELECT u.name as \"userName\", p.name as \"planName\"\n * FROM $tenant.users u\n * JOIN $shared.plans p ON u.plan_id = p.id\n * `,\n * });\n * ```\n */\nexport async function crossSchemaRaw<TResult = Record<string, unknown>>(\n db: NodePgDatabase<Record<string, unknown>>,\n options: CrossSchemaRawOptions\n): Promise<TResult[]> {\n const { tenantSchema, sharedSchema, sql: rawSql } = options;\n\n // Replace $tenant and $shared placeholders\n const processedSql = rawSql\n .replace(/\\$tenant\\./g, `\"${tenantSchema}\".`)\n .replace(/\\$shared\\./g, `\"${sharedSchema}\".`);\n\n const query = sql.raw(processedSql);\n\n const result = await db.execute(query);\n\n return result.rows as TResult[];\n}\n\n/**\n * Create a typed cross-schema query using SQL template\n *\n * @example\n * ```typescript\n * const users = await crossSchemaSelect(tenantDb, {\n * tenantSchema: 'tenant_abc',\n * sharedSchema: 'public',\n * select: {\n * id: users.id,\n * name: users.name,\n * planName: plans.name,\n * },\n * from: { table: users, schema: 'tenant' },\n * joins: [\n * { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },\n * ],\n * });\n * ```\n */\nexport function buildCrossSchemaSelect<T extends Record<string, Column>>(\n fields: T,\n tenantSchema: string,\n _sharedSchema: string\n): { columns: string[]; getSchema: () => string } {\n const columns = Object.entries(fields).map(([alias, column]) => {\n const columnName = column.name;\n return `\"${columnName}\" as \"${alias}\"`;\n });\n\n const getSchema = (): string => {\n // This would need more context to determine which schema a column belongs to\n // For now, return tenant schema as default\n return tenantSchema;\n };\n\n return { columns, getSchema };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cross-schema/cross-schema.ts","../../src/cross-schema/with-shared.ts"],"names":["sql","getTableName"],"mappings":"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","file":"index.js","sourcesContent":["import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Table, Column } from 'drizzle-orm';\nimport type {\n CrossSchemaContext,\n SchemaSource,\n JoinType,\n JoinCondition,\n SharedLookupConfig,\n CrossSchemaRawOptions,\n} from './types.js';\n\n/**\n * Cross-schema query builder for joining tenant and shared data\n *\n * @example\n * ```typescript\n * const query = createCrossSchemaQuery({\n * tenantDb: tenants.getDb('tenant-uuid'),\n * sharedDb: tenants.getSharedDb(),\n * });\n *\n * const results = await query\n * .from('tenant', orders)\n * .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))\n * .select({\n * orderId: orders.id,\n * planName: subscriptionPlans.name,\n * })\n * .execute();\n * ```\n */\nexport class CrossSchemaQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: { table: Table; source: SchemaSource; schemaName: string } | null = null;\n private joins: Array<{\n table: Table;\n source: SchemaSource;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(private readonly context: CrossSchemaContext<TTenantSchema, TSharedSchema>) {}\n\n /**\n * Set the main table to query from\n */\n from<T extends Table>(source: SchemaSource, table: T): this {\n const schemaName = this.getSchemaName(source);\n this.fromTable = { table, source, schemaName };\n return this;\n }\n\n /**\n * Add an inner join\n */\n innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'inner');\n }\n\n /**\n * Add a left join\n */\n leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'left');\n }\n\n /**\n * Add a right join\n */\n rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'right');\n }\n\n /**\n * Add a full outer join\n */\n fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this {\n return this.addJoin(source, table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a where condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add order by\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set limit\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set offset\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult = Record<string, unknown>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n\n // Use the tenant db to execute (it has access to both schemas via search_path)\n const result = await this.context.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause\n const fromTableRef = this.getFullTableName(this.fromTable.schemaName, this.fromTable.table);\n parts.push(sql` FROM ${sql.raw(fromTableRef)}`);\n\n // JOIN clauses\n for (const join of this.joins) {\n const joinTableRef = this.getFullTableName(join.schemaName, join.table);\n const joinType = this.getJoinKeyword(join.type);\n parts.push(sql` ${sql.raw(joinType)} ${sql.raw(joinTableRef)} ON ${join.condition}`);\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n source: SchemaSource,\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const schemaName = this.getSchemaName(source);\n this.joins.push({ table, source, schemaName, condition, type });\n return this;\n }\n\n /**\n * Get schema name for a source\n */\n private getSchemaName(source: SchemaSource): string {\n if (source === 'tenant') {\n return this.context.tenantSchema ?? 'tenant';\n }\n return this.context.sharedSchema ?? 'public';\n }\n\n /**\n * Get fully qualified table name\n */\n private getFullTableName(schemaName: string, table: Table): string {\n const tableName = getTableName(table);\n return `\"${schemaName}\".\"${tableName}\"`;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a cross-schema query builder\n */\nexport function createCrossSchemaQuery<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n>(\n context: CrossSchemaContext<TTenantSchema, TSharedSchema>\n): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema> {\n return new CrossSchemaQueryBuilder(context);\n}\n\n/**\n * Helper for common pattern: tenant table with shared lookup\n *\n * @example\n * ```typescript\n * const ordersWithPlans = await withSharedLookup({\n * tenantDb,\n * sharedDb,\n * tenantTable: orders,\n * sharedTable: subscriptionPlans,\n * foreignKey: 'planId',\n * sharedFields: ['name', 'features', 'price'],\n * });\n * ```\n */\nexport async function withSharedLookup<\n TTenantTable extends Table,\n TSharedTable extends Table,\n TSharedFields extends keyof TSharedTable['_']['columns'],\n>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>> {\n const {\n tenantDb,\n tenantTable,\n sharedTable,\n foreignKey,\n sharedKey = 'id' as keyof TSharedTable['_']['columns'],\n sharedFields,\n where: whereCondition,\n } = config;\n\n // Get table names using Drizzle's utility\n const tenantTableName = getTableName(tenantTable);\n const sharedTableName = getTableName(sharedTable);\n\n // Build field list for shared table\n const sharedFieldList = sharedFields\n .map((field) => `s.\"${String(field)}\"`)\n .join(', ');\n\n // Build the query\n const queryParts = [\n `SELECT t.*, ${sharedFieldList}`,\n `FROM \"${tenantTableName}\" t`,\n `LEFT JOIN \"public\".\"${sharedTableName}\" s ON t.\"${String(foreignKey)}\" = s.\"${String(sharedKey)}\"`,\n ];\n\n if (whereCondition) {\n queryParts.push('WHERE');\n // We'll need to use raw SQL for the where condition\n }\n\n const sqlQuery = sql.raw(queryParts.join(' '));\n\n const result = await tenantDb.execute(sqlQuery);\n\n return result.rows as Array<Record<string, unknown>>;\n}\n\n/**\n * Execute raw cross-schema SQL with type safety\n *\n * @example\n * ```typescript\n * const result = await crossSchemaRaw<{ userName: string; planName: string }>({\n * tenantSchema: 'tenant_abc123',\n * sharedSchema: 'public',\n * sql: `\n * SELECT u.name as \"userName\", p.name as \"planName\"\n * FROM $tenant.users u\n * JOIN $shared.plans p ON u.plan_id = p.id\n * `,\n * });\n * ```\n */\nexport async function crossSchemaRaw<TResult = Record<string, unknown>>(\n db: NodePgDatabase<Record<string, unknown>>,\n options: CrossSchemaRawOptions\n): Promise<TResult[]> {\n const { tenantSchema, sharedSchema, sql: rawSql } = options;\n\n // Replace $tenant and $shared placeholders\n const processedSql = rawSql\n .replace(/\\$tenant\\./g, `\"${tenantSchema}\".`)\n .replace(/\\$shared\\./g, `\"${sharedSchema}\".`);\n\n const query = sql.raw(processedSql);\n\n const result = await db.execute(query);\n\n return result.rows as TResult[];\n}\n\n/**\n * Create a typed cross-schema query using SQL template\n *\n * @example\n * ```typescript\n * const users = await crossSchemaSelect(tenantDb, {\n * tenantSchema: 'tenant_abc',\n * sharedSchema: 'public',\n * select: {\n * id: users.id,\n * name: users.name,\n * planName: plans.name,\n * },\n * from: { table: users, schema: 'tenant' },\n * joins: [\n * { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },\n * ],\n * });\n * ```\n */\nexport function buildCrossSchemaSelect<T extends Record<string, Column>>(\n fields: T,\n tenantSchema: string,\n _sharedSchema: string\n): { columns: string[]; getSchema: () => string } {\n const columns = Object.entries(fields).map(([alias, column]) => {\n const columnName = column.name;\n return `\"${columnName}\" as \"${alias}\"`;\n });\n\n const getSchema = (): string => {\n // This would need more context to determine which schema a column belongs to\n // For now, return tenant schema as default\n return tenantSchema;\n };\n\n return { columns, getSchema };\n}\n","import { sql, getTableName } from 'drizzle-orm';\nimport type { NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport type { SQL, Column, Table } from 'drizzle-orm';\nimport type {\n JoinCondition,\n JoinType,\n WithSharedConfig,\n WithSharedOptions,\n InferSelectResult,\n} from './types.js';\n\n/**\n * Extract tables from a Drizzle schema object\n */\nfunction extractTablesFromSchema(schema: Record<string, unknown>): Set<Table> {\n const tables = new Set<Table>();\n\n for (const value of Object.values(schema)) {\n if (value && typeof value === 'object' && '_' in value) {\n const branded = value as { _?: { brand?: string } };\n if (branded._?.brand === 'Table') {\n tables.add(value as Table);\n }\n }\n }\n\n return tables;\n}\n\n/**\n * Check if a table belongs to the shared schema\n */\nfunction isSharedTable(table: Table, sharedTables: Set<Table>): boolean {\n return sharedTables.has(table);\n}\n\n/**\n * Simplified cross-schema query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * const result = await withShared(tenantDb, sharedDb, { tenant: tenantSchema, shared: sharedSchema })\n * .from(pedidos)\n * .leftJoin(workflowSteps, eq(pedidos.workflowStepId, workflowSteps.id))\n * .select({ pedidoId: pedidos.id, workflowNome: workflowSteps.nome })\n * .execute();\n * ```\n */\nexport class WithSharedQueryBuilder<\n TTenantSchema extends Record<string, unknown> = Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _TSharedSchema extends Record<string, unknown> = Record<string, unknown>,\n> {\n private fromTable: {\n table: Table;\n isShared: boolean;\n schemaName: string;\n } | null = null;\n\n private joins: Array<{\n table: Table;\n isShared: boolean;\n schemaName: string;\n condition: JoinCondition;\n type: JoinType;\n }> = [];\n\n private selectFields: Record<string, Column> = {};\n private whereCondition: SQL<unknown> | null = null;\n private orderByFields: SQL<unknown>[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n\n constructor(\n private readonly tenantDb: NodePgDatabase<TTenantSchema>,\n private readonly sharedTables: Set<Table>,\n private readonly tenantSchemaName: string,\n private readonly sharedSchemaName: string = 'public'\n ) {}\n\n /**\n * Set the main table to query from\n * Automatically detects if it's a tenant or shared table\n */\n from<T extends Table>(table: T): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.fromTable = {\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n };\n return this;\n }\n\n /**\n * Add a left join with automatic schema detection\n */\n leftJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'left');\n }\n\n /**\n * Add an inner join with automatic schema detection\n */\n innerJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'inner');\n }\n\n /**\n * Add a right join with automatic schema detection\n */\n rightJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'right');\n }\n\n /**\n * Add a full outer join with automatic schema detection\n */\n fullJoin<T extends Table>(table: T, condition: JoinCondition): this {\n return this.addJoin(table, condition, 'full');\n }\n\n /**\n * Select specific fields\n */\n select<T extends Record<string, Column>>(fields: T): this {\n this.selectFields = fields;\n return this;\n }\n\n /**\n * Add a WHERE condition\n */\n where(condition: SQL<unknown>): this {\n this.whereCondition = condition;\n return this;\n }\n\n /**\n * Add ORDER BY\n */\n orderBy(...fields: SQL<unknown>[]): this {\n this.orderByFields = fields;\n return this;\n }\n\n /**\n * Set LIMIT\n */\n limit(value: number): this {\n this.limitValue = value;\n return this;\n }\n\n /**\n * Set OFFSET\n */\n offset(value: number): this {\n this.offsetValue = value;\n return this;\n }\n\n /**\n * Execute the query and return typed results\n */\n async execute<TResult extends Record<string, unknown> = InferSelectResult<typeof this.selectFields>>(): Promise<TResult[]> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified. Use .from() first.');\n }\n\n const sqlQuery = this.buildSql();\n const result = await this.tenantDb.execute(sqlQuery);\n\n return result.rows as TResult[];\n }\n\n /**\n * Add a join to the query\n */\n private addJoin<T extends Table>(\n table: T,\n condition: JoinCondition,\n type: JoinType\n ): this {\n const isShared = isSharedTable(table, this.sharedTables);\n this.joins.push({\n table,\n isShared,\n schemaName: isShared ? this.sharedSchemaName : this.tenantSchemaName,\n condition,\n type,\n });\n return this;\n }\n\n /**\n * Build the SQL query\n */\n private buildSql(): SQL<unknown> {\n if (!this.fromTable) {\n throw new Error('[drizzle-multitenant] No table specified');\n }\n\n const parts: SQL<unknown>[] = [];\n\n // SELECT clause\n const selectParts = Object.entries(this.selectFields).map(([alias, column]) => {\n const columnName = column.name;\n // Try to get table name from column\n const tableName = this.getTableAliasForColumn(column);\n if (tableName) {\n return sql`${sql.raw(`\"${tableName}\".\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n }\n return sql`${sql.raw(`\"${columnName}\"`)} as ${sql.raw(`\"${alias}\"`)}`;\n });\n\n if (selectParts.length === 0) {\n parts.push(sql`SELECT *`);\n } else {\n parts.push(sql`SELECT ${sql.join(selectParts, sql`, `)}`);\n }\n\n // FROM clause with alias\n const fromTableName = getTableName(this.fromTable.table);\n const fromTableRef = `\"${this.fromTable.schemaName}\".\"${fromTableName}\"`;\n parts.push(sql` FROM ${sql.raw(fromTableRef)} \"${sql.raw(fromTableName)}\"`);\n\n // JOIN clauses with aliases\n for (const join of this.joins) {\n const joinTableName = getTableName(join.table);\n const joinTableRef = `\"${join.schemaName}\".\"${joinTableName}\"`;\n const joinKeyword = this.getJoinKeyword(join.type);\n parts.push(\n sql` ${sql.raw(joinKeyword)} ${sql.raw(joinTableRef)} \"${sql.raw(joinTableName)}\" ON ${join.condition}`\n );\n }\n\n // WHERE clause\n if (this.whereCondition) {\n parts.push(sql` WHERE ${this.whereCondition}`);\n }\n\n // ORDER BY clause\n if (this.orderByFields.length > 0) {\n parts.push(sql` ORDER BY ${sql.join(this.orderByFields, sql`, `)}`);\n }\n\n // LIMIT clause\n if (this.limitValue !== null) {\n parts.push(sql` LIMIT ${sql.raw(this.limitValue.toString())}`);\n }\n\n // OFFSET clause\n if (this.offsetValue !== null) {\n parts.push(sql` OFFSET ${sql.raw(this.offsetValue.toString())}`);\n }\n\n return sql.join(parts, sql``);\n }\n\n /**\n * Get table alias for a column (used in SELECT)\n */\n private getTableAliasForColumn(column: Column): string | null {\n // Drizzle columns have a reference to their table\n const columnTable = (column as unknown as { table?: Table }).table;\n if (columnTable) {\n return getTableName(columnTable);\n }\n return null;\n }\n\n /**\n * Get SQL keyword for join type\n */\n private getJoinKeyword(type: JoinType): string {\n switch (type) {\n case 'inner':\n return 'INNER JOIN';\n case 'left':\n return 'LEFT JOIN';\n case 'right':\n return 'RIGHT JOIN';\n case 'full':\n return 'FULL OUTER JOIN';\n }\n }\n}\n\n/**\n * Create a simplified cross-schema query builder with automatic schema detection\n *\n * This helper automatically detects whether a table belongs to the tenant schema\n * or the shared schema based on the schema configuration provided.\n *\n * @param tenantDb - The tenant database instance\n * @param sharedDb - The shared database instance (unused but kept for API symmetry)\n * @param schemas - Object containing tenant and shared schema definitions\n * @param options - Optional configuration for schema names\n * @returns A query builder with automatic schema detection\n *\n * @example\n * ```typescript\n * // Define your schemas\n * const tenantSchema = { pedidos, clientes };\n * const sharedSchema = { workflowSteps, plans };\n *\n * // Use withShared for cross-schema queries\n * const result = await withShared(\n * tenantDb,\n * sharedDb,\n * { tenant: tenantSchema, shared: sharedSchema }\n * )\n * .from(pedidos) // Auto-detected as tenant table\n * .leftJoin(workflowSteps, // Auto-detected as shared table\n * eq(pedidos.workflowStepId, workflowSteps.id)\n * )\n * .select({\n * pedidoId: pedidos.id,\n * workflowNome: workflowSteps.nome,\n * })\n * .where(eq(pedidos.status, 'active'))\n * .orderBy(desc(pedidos.createdAt))\n * .limit(10)\n * .execute();\n * ```\n */\nexport function withShared<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantDb: NodePgDatabase<TTenantSchema>,\n _sharedDb: NodePgDatabase<TSharedSchema>,\n schemas: WithSharedConfig<TTenantSchema, TSharedSchema>,\n options?: WithSharedOptions\n): WithSharedQueryBuilder<TTenantSchema, TSharedSchema> {\n const sharedTables = extractTablesFromSchema(schemas.shared);\n\n return new WithSharedQueryBuilder(\n tenantDb,\n sharedTables,\n options?.tenantSchema ?? 'tenant',\n options?.sharedSchema ?? 'public'\n );\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as Config, T as TenantManager } from './types-
|
|
2
|
-
export { b as ConnectionConfig,
|
|
3
|
-
export { B as BaseTenantContext, a as TenantContext, T as TenantContextData, c as createTenantContext } from './context-
|
|
1
|
+
import { C as Config, T as TenantManager, R as RetryConfig } from './types-B5eSRLFW.js';
|
|
2
|
+
export { b as ConnectionConfig, h as DEFAULT_CONFIG, D as DebugConfig, e as DebugContext, H as Hooks, I as IsolationConfig, c as IsolationStrategy, M as MetricsConfig, P as PoolEntry, d as SchemasConfig, S as SharedDb, a as TenantDb, g as TenantWarmupResult, W as WarmupOptions, f as WarmupResult } from './types-B5eSRLFW.js';
|
|
3
|
+
export { B as BaseTenantContext, a as TenantContext, T as TenantContextData, c as createTenantContext } from './context-DoHx79MS.js';
|
|
4
4
|
export { AppliedMigration, CreateTenantOptions, DropTenantOptions, MigrateOptions, MigrationErrorHandler, MigrationFile, MigrationHooks, MigrationProgressCallback, MigrationResults, Migrator, MigratorConfig, TenantMigrationResult, TenantMigrationStatus, createMigrator } from './migrator/index.js';
|
|
5
|
-
export { ColumnSelection, CrossSchemaContext, CrossSchemaQueryBuilder, CrossSchemaRawOptions, InferSelectedColumns, JoinCondition, JoinDefinition, JoinType, LookupResult, SchemaSource, SharedLookupConfig, TableReference, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withSharedLookup } from './cross-schema/index.js';
|
|
5
|
+
export { ColumnSelection, CrossSchemaContext, CrossSchemaQueryBuilder, CrossSchemaRawOptions, InferSelectResult, InferSelectedColumns, JoinCondition, JoinDefinition, JoinType, LookupResult, SchemaSource, SharedLookupConfig, TableReference, WithSharedConfig, WithSharedOptions, WithSharedQueryBuilder, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withShared, withSharedLookup } from './cross-schema/index.js';
|
|
6
6
|
import 'pg';
|
|
7
7
|
import 'drizzle-orm/node-postgres';
|
|
8
8
|
import 'drizzle-orm';
|
|
@@ -68,4 +68,61 @@ declare function defineConfig<TTenantSchema extends Record<string, unknown>, TSh
|
|
|
68
68
|
*/
|
|
69
69
|
declare function createTenantManager<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>>(config: Config<TTenantSchema, TSharedSchema>): TenantManager<TTenantSchema, TSharedSchema>;
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Default function to determine if an error is retryable
|
|
73
|
+
* Focuses on transient connection errors
|
|
74
|
+
*/
|
|
75
|
+
declare function isRetryableError(error: Error): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Calculate delay with exponential backoff and optional jitter
|
|
78
|
+
*/
|
|
79
|
+
declare function calculateDelay(attempt: number, config: Required<Pick<RetryConfig, 'initialDelayMs' | 'maxDelayMs' | 'backoffMultiplier' | 'jitter'>>): number;
|
|
80
|
+
/**
|
|
81
|
+
* Retry result with metadata
|
|
82
|
+
*/
|
|
83
|
+
interface RetryResult<T> {
|
|
84
|
+
/** The result value if successful */
|
|
85
|
+
result: T;
|
|
86
|
+
/** Number of attempts made (1 = first try succeeded) */
|
|
87
|
+
attempts: number;
|
|
88
|
+
/** Total time spent including retries in ms */
|
|
89
|
+
totalTimeMs: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Retry an async operation with exponential backoff
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const result = await withRetry(
|
|
97
|
+
* () => pool.connect(),
|
|
98
|
+
* {
|
|
99
|
+
* maxAttempts: 3,
|
|
100
|
+
* initialDelayMs: 100,
|
|
101
|
+
* maxDelayMs: 5000,
|
|
102
|
+
* backoffMultiplier: 2,
|
|
103
|
+
* onRetry: (attempt, error, delay) => {
|
|
104
|
+
* console.log(`Retry ${attempt} after ${delay}ms: ${error.message}`);
|
|
105
|
+
* },
|
|
106
|
+
* }
|
|
107
|
+
* );
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
declare function withRetry<T>(operation: () => Promise<T>, config?: RetryConfig): Promise<RetryResult<T>>;
|
|
111
|
+
/**
|
|
112
|
+
* Create a retry wrapper with pre-configured options
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const retrier = createRetrier({
|
|
117
|
+
* maxAttempts: 5,
|
|
118
|
+
* initialDelayMs: 200,
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* // Use the same config for multiple operations
|
|
122
|
+
* const result1 = await retrier(() => connectToDb());
|
|
123
|
+
* const result2 = await retrier(() => fetchData());
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare function createRetrier(config: RetryConfig): <T>(operation: () => Promise<T>) => Promise<RetryResult<T>>;
|
|
127
|
+
|
|
128
|
+
export { Config, RetryConfig, type RetryResult, TenantManager, calculateDelay, createRetrier, createTenantManager, defineConfig, isRetryableError, withRetry };
|