@elysiumjs/drizzle 0.0.0-stage → 0.1.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,301 @@
1
+ import type { FileCondition, FilePatch, FileRecord, FileStatus, FileStoreDriver } from '@elysiumjs/olympus/pithos';
2
+ import type { DrizzleStoreOptions, StoreTable } from './moirai';
3
+ declare module '@elysiumjs/olympus' {
4
+ interface PortDrivers {
5
+ 'file-store:drizzle': typeof DrizzleFileStore;
6
+ }
7
+ }
8
+ /**
9
+ * Builds the table of the file store, in a schema when one is given. Export it from the Drizzle
10
+ * schema so that `migration:generate` creates it.
11
+ * @author Axel Nana <ax.lnana@outlook.com>
12
+ * @param name The name of the table. Defaults to `files`.
13
+ * @param schema The Postgres schema of the table. Defaults to the search path.
14
+ * @example
15
+ * ```ts
16
+ * export const files = filesTable();
17
+ *
18
+ * PithosModule.with({ disks, files: { store: () => FileStore.for('drizzle', { table: files }) } });
19
+ * ```
20
+ */
21
+ export declare const filesTable: (name?: string, schema?: string) => import("drizzle-orm/pg-core").PgTableWithColumns<{
22
+ name: string;
23
+ schema: undefined;
24
+ columns: {
25
+ id: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetIsPrimaryKey<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
26
+ name: string;
27
+ tableName: string;
28
+ dataType: "string";
29
+ data: string;
30
+ driverParam: string;
31
+ notNull: true;
32
+ hasDefault: false;
33
+ isPrimaryKey: false;
34
+ isAutoincrement: false;
35
+ hasRuntimeDefault: false;
36
+ enumValues: undefined;
37
+ identity: undefined;
38
+ generated: undefined;
39
+ }>;
40
+ purpose: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
41
+ name: string;
42
+ tableName: string;
43
+ dataType: "string";
44
+ data: string;
45
+ driverParam: string;
46
+ notNull: true;
47
+ hasDefault: false;
48
+ isPrimaryKey: false;
49
+ isAutoincrement: false;
50
+ hasRuntimeDefault: false;
51
+ enumValues: undefined;
52
+ identity: undefined;
53
+ generated: undefined;
54
+ }>;
55
+ disk: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
56
+ name: string;
57
+ tableName: string;
58
+ dataType: "string";
59
+ data: string;
60
+ driverParam: string;
61
+ notNull: true;
62
+ hasDefault: false;
63
+ isPrimaryKey: false;
64
+ isAutoincrement: false;
65
+ hasRuntimeDefault: false;
66
+ enumValues: undefined;
67
+ identity: undefined;
68
+ generated: undefined;
69
+ }>;
70
+ key: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
71
+ name: string;
72
+ tableName: string;
73
+ dataType: "string";
74
+ data: string;
75
+ driverParam: string;
76
+ notNull: true;
77
+ hasDefault: false;
78
+ isPrimaryKey: false;
79
+ isAutoincrement: false;
80
+ hasRuntimeDefault: false;
81
+ enumValues: undefined;
82
+ identity: undefined;
83
+ generated: undefined;
84
+ }>;
85
+ contentType: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
86
+ name: string;
87
+ tableName: string;
88
+ dataType: "string";
89
+ data: string;
90
+ driverParam: string;
91
+ notNull: true;
92
+ hasDefault: false;
93
+ isPrimaryKey: false;
94
+ isAutoincrement: false;
95
+ hasRuntimeDefault: false;
96
+ enumValues: undefined;
97
+ identity: undefined;
98
+ generated: undefined;
99
+ }>;
100
+ size: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgBigInt53Builder>, {
101
+ name: string;
102
+ tableName: string;
103
+ dataType: "number int53";
104
+ data: number;
105
+ driverParam: string | number;
106
+ notNull: true;
107
+ hasDefault: false;
108
+ isPrimaryKey: false;
109
+ isAutoincrement: false;
110
+ hasRuntimeDefault: false;
111
+ enumValues: undefined;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }>;
115
+ ownerType: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
116
+ name: string;
117
+ tableName: string;
118
+ dataType: "string";
119
+ data: string;
120
+ driverParam: string;
121
+ notNull: true;
122
+ hasDefault: false;
123
+ isPrimaryKey: false;
124
+ isAutoincrement: false;
125
+ hasRuntimeDefault: false;
126
+ enumValues: undefined;
127
+ identity: undefined;
128
+ generated: undefined;
129
+ }>;
130
+ ownerId: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>>, {
131
+ name: string;
132
+ tableName: string;
133
+ dataType: "string";
134
+ data: string;
135
+ driverParam: string;
136
+ notNull: true;
137
+ hasDefault: false;
138
+ isPrimaryKey: false;
139
+ isAutoincrement: false;
140
+ hasRuntimeDefault: false;
141
+ enumValues: undefined;
142
+ identity: undefined;
143
+ generated: undefined;
144
+ }>;
145
+ createdBy: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, {
146
+ name: string;
147
+ tableName: string;
148
+ dataType: "string";
149
+ data: string;
150
+ driverParam: string;
151
+ notNull: false;
152
+ hasDefault: false;
153
+ isPrimaryKey: false;
154
+ isAutoincrement: false;
155
+ hasRuntimeDefault: false;
156
+ enumValues: undefined;
157
+ identity: undefined;
158
+ generated: undefined;
159
+ }>;
160
+ status: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, FileStatus>>, {
161
+ name: string;
162
+ tableName: string;
163
+ dataType: "string";
164
+ data: FileStatus;
165
+ driverParam: string;
166
+ notNull: true;
167
+ hasDefault: false;
168
+ isPrimaryKey: false;
169
+ isAutoincrement: false;
170
+ hasRuntimeDefault: false;
171
+ enumValues: undefined;
172
+ identity: undefined;
173
+ generated: undefined;
174
+ }>;
175
+ createdAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgTimestampBuilder>, {
176
+ name: string;
177
+ tableName: string;
178
+ dataType: "object date";
179
+ data: Date;
180
+ driverParam: string;
181
+ notNull: true;
182
+ hasDefault: false;
183
+ isPrimaryKey: false;
184
+ isAutoincrement: false;
185
+ hasRuntimeDefault: false;
186
+ enumValues: undefined;
187
+ identity: undefined;
188
+ generated: undefined;
189
+ }>;
190
+ readyAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
191
+ name: string;
192
+ tableName: string;
193
+ dataType: "object date";
194
+ data: Date;
195
+ driverParam: string;
196
+ notNull: false;
197
+ hasDefault: false;
198
+ isPrimaryKey: false;
199
+ isAutoincrement: false;
200
+ hasRuntimeDefault: false;
201
+ enumValues: undefined;
202
+ identity: undefined;
203
+ generated: undefined;
204
+ }>;
205
+ claimedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
206
+ name: string;
207
+ tableName: string;
208
+ dataType: "object date";
209
+ data: Date;
210
+ driverParam: string;
211
+ notNull: false;
212
+ hasDefault: false;
213
+ isPrimaryKey: false;
214
+ isAutoincrement: false;
215
+ hasRuntimeDefault: false;
216
+ enumValues: undefined;
217
+ identity: undefined;
218
+ generated: undefined;
219
+ }>;
220
+ releasedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
221
+ name: string;
222
+ tableName: string;
223
+ dataType: "object date";
224
+ data: Date;
225
+ driverParam: string;
226
+ notNull: false;
227
+ hasDefault: false;
228
+ isPrimaryKey: false;
229
+ isAutoincrement: false;
230
+ hasRuntimeDefault: false;
231
+ enumValues: undefined;
232
+ identity: undefined;
233
+ generated: undefined;
234
+ }>;
235
+ expiresAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
236
+ name: string;
237
+ tableName: string;
238
+ dataType: "object date";
239
+ data: Date;
240
+ driverParam: string;
241
+ notNull: false;
242
+ hasDefault: false;
243
+ isPrimaryKey: false;
244
+ isAutoincrement: false;
245
+ hasRuntimeDefault: false;
246
+ enumValues: undefined;
247
+ identity: undefined;
248
+ generated: undefined;
249
+ }>;
250
+ deletedAt: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTimestampBuilder, {
251
+ name: string;
252
+ tableName: string;
253
+ dataType: "object date";
254
+ data: Date;
255
+ driverParam: string;
256
+ notNull: false;
257
+ hasDefault: false;
258
+ isPrimaryKey: false;
259
+ isAutoincrement: false;
260
+ hasRuntimeDefault: false;
261
+ enumValues: undefined;
262
+ identity: undefined;
263
+ generated: undefined;
264
+ }>;
265
+ rejection: import("drizzle-orm/pg-core").PgBuildColumn<string, import("drizzle-orm/pg-core").PgTextBuilder<[string, ...string[]]>, {
266
+ name: string;
267
+ tableName: string;
268
+ dataType: "string";
269
+ data: string;
270
+ driverParam: string;
271
+ notNull: false;
272
+ hasDefault: false;
273
+ isPrimaryKey: false;
274
+ isAutoincrement: false;
275
+ hasRuntimeDefault: false;
276
+ enumValues: undefined;
277
+ identity: undefined;
278
+ generated: undefined;
279
+ }>;
280
+ };
281
+ dialect: 'pg';
282
+ }>;
283
+ /** The table `filesTable()` builds. */
284
+ export type FilesTable = ReturnType<typeof filesTable>;
285
+ /**
286
+ * Keeps file records in a Postgres table, built with `filesTable()` or any table with its
287
+ * columns. Each transition is one conditional `UPDATE`, so only one of two racing requests wins.
288
+ * @author Axel Nana <ax.lnana@outlook.com>
289
+ */
290
+ export declare class DrizzleFileStore implements FileStoreDriver {
291
+ private readonly options;
292
+ constructor(options: DrizzleStoreOptions<StoreTable<FilesTable>>);
293
+ /** The table, read through the columns of the files table, which it has. */
294
+ private get table();
295
+ private get db();
296
+ insert({ owner, ...record }: FileRecord): Promise<void>;
297
+ find(id: string): Promise<FileRecord | null>;
298
+ transition(id: string, when: FileCondition, patch: FilePatch): Promise<FileRecord | null>;
299
+ countPending(createdBy: string, now: Date): Promise<number>;
300
+ due(now: Date, limit: number): Promise<FileRecord[]>;
301
+ }
@@ -0,0 +1,28 @@
1
+ import type { ParsedFilter, ParsedQuery } from '@elysiumjs/olympus/mnemosyne';
2
+ import type { SQL } from 'drizzle-orm';
3
+ import type { PgTableWithColumns } from 'drizzle-orm/pg-core';
4
+ /**
5
+ * Compiles one filter of a parsed query to a Drizzle condition.
6
+ * @author Axel Nana <ax.lnana@outlook.com>
7
+ * @param table The table queried.
8
+ * @param filter The filter.
9
+ */
10
+ export declare const compileFilter: (table: PgTableWithColumns<any>, filter: ParsedFilter) => SQL;
11
+ /**
12
+ * Compiles the condition that keeps the rows after the cursor, in sort order: a keyset condition
13
+ * over every sort key, the row key last.
14
+ * @author Axel Nana <ax.lnana@outlook.com>
15
+ * @param table The table queried.
16
+ * @param query The parsed query, with `after` set.
17
+ */
18
+ export declare const compileAfter: (table: PgTableWithColumns<any>, query: ParsedQuery) => SQL | undefined;
19
+ /**
20
+ * Compiles a parsed query: the `where` condition (filters and cursor) and the `order by`.
21
+ * @author Axel Nana <ax.lnana@outlook.com>
22
+ * @param table The table queried.
23
+ * @param query The parsed query.
24
+ */
25
+ export declare const compileQuery: (table: PgTableWithColumns<any>, query: ParsedQuery) => {
26
+ where: SQL<unknown> | undefined;
27
+ orderBy: SQL<unknown>[];
28
+ };
@@ -0,0 +1,20 @@
1
+ import type { RepositoryAdapter } from '@elysiumjs/olympus/mnemosyne';
2
+ import type { SQL } from 'drizzle-orm';
3
+ import type { PgTable } from 'drizzle-orm/pg-core';
4
+ import type { DrizzleConnection } from './database';
5
+ declare module '@elysiumjs/olympus/mnemosyne' {
6
+ interface RepositoryDrivers {
7
+ drizzle: {
8
+ table: PgTable;
9
+ connection: DrizzleConnection;
10
+ scope: SQL;
11
+ };
12
+ }
13
+ }
14
+ /**
15
+ * The repository adapter of Drizzle: `Repository(Model)` runs on it for the models of
16
+ * `DrizzleModel()`. Statements join the transaction open on the connection, and honour the
17
+ * tenant isolation of row-level security.
18
+ * @author Axel Nana <ax.lnana@outlook.com>
19
+ */
20
+ export declare const drizzleRepositoryAdapter: RepositoryAdapter<PgTable, DrizzleConnection, SQL>;
@@ -0,0 +1,97 @@
1
+ import type { SQL } from 'drizzle-orm';
2
+ import type { AnyPgColumn, PgTable } from 'drizzle-orm/pg-core';
3
+ /**
4
+ * A table as the SQL that follows its creation sees it.
5
+ * @author Axel Nana <ax.lnana@outlook.com>
6
+ */
7
+ export type CreatedTable = {
8
+ /** The Postgres schema of the table, `undefined` for `public`. */
9
+ readonly schema: string | undefined;
10
+ /** The name of the table. */
11
+ readonly name: string;
12
+ /** The quoted, schema-qualified name of the table: `"kernel"."audit"`. */
13
+ readonly qualified: string;
14
+ };
15
+ /**
16
+ * A column a partition key is made of: its name in the database, or a function returning the
17
+ * column of the table.
18
+ */
19
+ export type PartitionColumn = string | ((table: any) => AnyPgColumn);
20
+ /**
21
+ * What `migration:generate` adds to the migration that creates a table.
22
+ * @author Axel Nana <ax.lnana@outlook.com>
23
+ */
24
+ export type TableMarker = {
25
+ /** The columns of the range partition key. */
26
+ readonly range?: readonly PartitionColumn[];
27
+ /** The SQL to run after the table is created. */
28
+ readonly afterCreate?: ReadonlyArray<(table: CreatedTable) => string | SQL>;
29
+ };
30
+ /**
31
+ * Attaches markers to a table, after the ones it already has.
32
+ * @author Axel Nana <ax.lnana@outlook.com>
33
+ * @param table The table.
34
+ * @param markers The markers.
35
+ * @returns The table.
36
+ */
37
+ export declare const markTable: <T extends PgTable>(table: T, markers: readonly TableMarker[]) => T;
38
+ /**
39
+ * Reads the markers of a table.
40
+ * @author Axel Nana <ax.lnana@outlook.com>
41
+ * @param table The table.
42
+ * @returns The markers merged into one, or `undefined` when the table has none.
43
+ */
44
+ export declare const getTableMarker: (table: object) => TableMarker | undefined;
45
+ /**
46
+ * Applies the markers of the given tables to the migration that creates them: the partition key
47
+ * after `CREATE TABLE`, then the SQL to run after it, each as its own statement. A table the
48
+ * migration does not create is left as it is.
49
+ * @author Axel Nana <ax.lnana@outlook.com>
50
+ * @param sql The SQL of the migration, without the `public` qualifiers.
51
+ * @param tables The tables of the app.
52
+ * @returns The SQL with the markers applied.
53
+ */
54
+ export declare const applyTableMarkers: (sql: string, tables: Iterable<PgTable>) => string;
55
+ /**
56
+ * Drizzle tables: the markers that `migration:generate` applies to the migration creating a table.
57
+ * @author Axel Nana <ax.lnana@outlook.com>
58
+ */
59
+ export declare namespace DrizzleTable {
60
+ /**
61
+ * Marks a table with what `migration:generate` adds to the migration that creates it. Later
62
+ * migrations, and tables created before the markers were added, are left as they are.
63
+ * @example
64
+ * ```ts
65
+ * export const audit = DrizzleTable.define(
66
+ * DrizzleTable.partitioned({ range: 'recorded_at' }),
67
+ * DrizzleTable.afterCreate(
68
+ * ({ qualified }) =>
69
+ * `CREATE TRIGGER audit_append_only BEFORE UPDATE OR DELETE ON ${qualified} FOR EACH ROW EXECUTE FUNCTION forbid_change()`
70
+ * )
71
+ * )(
72
+ * kernel.table('audit', { ... }, (t) => [primaryKey({ columns: [t.id, t.recordedAt] })])
73
+ * );
74
+ * ```
75
+ * @author Axel Nana <ax.lnana@outlook.com>
76
+ * @param markers The markers, from `DrizzleTable.partitioned()` and `DrizzleTable.afterCreate()`.
77
+ * @returns A function marking the table and returning it.
78
+ */
79
+ const define: (...markers: TableMarker[]) => <T extends PgTable>(target: T) => T;
80
+ /**
81
+ * Creates the table partitioned by range: `PARTITION BY RANGE (...)` follows its `CREATE TABLE`.
82
+ * The primary key and the unique constraints of the table must include the partition columns.
83
+ * @author Axel Nana <ax.lnana@outlook.com>
84
+ * @param options The partition key: a column name in the database, a function returning the
85
+ * column, or several of them.
86
+ */
87
+ const partitioned: (options: {
88
+ range: PartitionColumn | readonly PartitionColumn[];
89
+ }) => TableMarker;
90
+ /**
91
+ * Runs SQL right after the table is created, in the same migration: partitions, triggers or
92
+ * grants that belong to the table.
93
+ * @author Axel Nana <ax.lnana@outlook.com>
94
+ * @param build Returns the SQL, as a string or a `sql` template, from the created table.
95
+ */
96
+ const afterCreate: (build: (table: CreatedTable) => string | SQL) => TableMarker;
97
+ }
@@ -0,0 +1,69 @@
1
+ import type { AnyPgColumnBuilder, PgTableWithColumns } from 'drizzle-orm/pg-core';
2
+ /**
3
+ * Retrieves the original column builders for a table.
4
+ * @param table The table created with enhanced pgTable.
5
+ * @returns The original column builder definitions, or `undefined`.
6
+ */
7
+ export declare const getTableBuilders: (table: PgTableWithColumns<any>) => Record<string, AnyPgColumnBuilder> | undefined;
8
+ /**
9
+ * Creates a PostgreSQL table with automatic column builder registration.
10
+ *
11
+ * This is an enhanced version of Drizzle's `pgTable` that automatically
12
+ * registers column builders for tenancy support. It has the exact same
13
+ * signature and behavior as the original.
14
+ *
15
+ * @param tableName The name of the database table.
16
+ * @param columns The column definitions.
17
+ * @param extraConfig Optional extra Drizzle table configuration.
18
+ * @returns A Drizzle PostgreSQL table with registered column builders.
19
+ */
20
+ export declare const pgTable: <TTableName extends string, TColumns extends Record<string, AnyPgColumnBuilder>>(tableName: TTableName, columns: TColumns, extraConfig?: (table: any) => any) => PgTableWithColumns<{
21
+ name: TTableName;
22
+ schema: undefined;
23
+ columns: { [Key in keyof TColumns]: import("drizzle-orm/pg-core").PgBuildColumn<TTableName, TColumns[Key], {
24
+ name: string;
25
+ tableName: TTableName;
26
+ dataType: TColumns[Key]["_"]["dataType"];
27
+ data: TColumns[Key]["_"]["dimensions"] extends 1 | 2 | 3 | 4 | 5 ? TColumns[Key]["_"]["dimensions"] extends infer T ? T extends TColumns[Key]["_"]["dimensions"] ? T extends 1 ? (TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
28
+ $type: infer U;
29
+ } ? U : T_1 extends {
30
+ data: infer D;
31
+ } ? D : unknown : never : never)[] : T extends 2 ? (TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
32
+ $type: infer U;
33
+ } ? U : T_1 extends {
34
+ data: infer D;
35
+ } ? D : unknown : never : never)[][] : T extends 3 ? (TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
36
+ $type: infer U;
37
+ } ? U : T_1 extends {
38
+ data: infer D;
39
+ } ? D : unknown : never : never)[][][] : T extends 4 ? (TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
40
+ $type: infer U;
41
+ } ? U : T_1 extends {
42
+ data: infer D;
43
+ } ? D : unknown : never : never)[][][][] : T extends 5 ? (TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
44
+ $type: infer U;
45
+ } ? U : T_1 extends {
46
+ data: infer D;
47
+ } ? D : unknown : never : never)[][][][][] : TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
48
+ $type: infer U;
49
+ } ? U : T_1 extends {
50
+ data: infer D;
51
+ } ? D : unknown : never : never : never : never : TColumns[Key]["_"] extends infer T_1 ? T_1 extends TColumns[Key]["_"] ? T_1 extends {
52
+ $type: infer U;
53
+ } ? U : T_1 extends {
54
+ data: infer D;
55
+ } ? D : unknown : never : never;
56
+ driverParam: TColumns[Key]["_"]["dimensions"] extends 1 | 2 | 3 | 4 | 5 ? string | (TColumns[Key]["_"]["dimensions"] extends infer T_2 ? T_2 extends TColumns[Key]["_"]["dimensions"] ? T_2 extends 1 ? TColumns[Key]["_"]["driverParam"][] : T_2 extends 2 ? TColumns[Key]["_"]["driverParam"][][] : T_2 extends 3 ? TColumns[Key]["_"]["driverParam"][][][] : T_2 extends 4 ? TColumns[Key]["_"]["driverParam"][][][][] : T_2 extends 5 ? TColumns[Key]["_"]["driverParam"][][][][][] : TColumns[Key]["_"]["driverParam"] : never : never) : TColumns[Key]["_"]["driverParam"];
57
+ notNull: TColumns[Key]["_"]["notNull"] extends true ? true : false;
58
+ hasDefault: TColumns[Key]["_"]["hasDefault"] extends true ? true : false;
59
+ isPrimaryKey: false;
60
+ isAutoincrement: false;
61
+ hasRuntimeDefault: false;
62
+ enumValues: TColumns[Key]["_"] extends infer T_3 ? T_3 extends TColumns[Key]["_"] ? T_3 extends {
63
+ enumValues: infer E extends string[];
64
+ } ? E : undefined : never : never;
65
+ identity: TColumns[Key]["_"]["identity"] extends "always" | "byDefault" ? TColumns[Key]["_"]["identity"] : undefined;
66
+ generated: TColumns[Key]["_"]["generated"] extends true ? true : undefined;
67
+ }>; };
68
+ dialect: 'pg';
69
+ }>;
@@ -0,0 +1,105 @@
1
+ import type { TenancyStrategy } from '@elysiumjs/olympus/mnemosyne';
2
+ import type { AnyPgColumnBuilder, PgAsyncTransaction, PgSchema, PgTable } from 'drizzle-orm/pg-core';
3
+ import type { DrizzleConnection } from './database';
4
+ /**
5
+ * Returns the Drizzle `PgSchema` for the given tenant, creating it if needed.
6
+ * @author Axel Nana <ax.lnana@outlook.com>
7
+ * @param tenant The tenant identifier.
8
+ * @returns The tenant's PostgreSQL schema.
9
+ * @throws {Error} If the tenant identifier is malformed.
10
+ */
11
+ export declare const getTenantSchema: (tenant: string) => PgSchema;
12
+ /**
13
+ * Registers a new tenant schema in the registry.
14
+ * @author Axel Nana <ax.lnana@outlook.com>
15
+ * @param tenant The tenant identifier.
16
+ * @returns The newly registered (or existing) `PgSchema`.
17
+ * @throws {Error} If the tenant identifier is malformed.
18
+ */
19
+ export declare const registerTenantSchema: (tenant: string) => PgSchema;
20
+ /**
21
+ * Wraps a table definition in a tenant-specific schema.
22
+ *
23
+ * For the `'public'` tenant, returns a standard `pgTable`.
24
+ * For other tenants, creates a schema-qualified table and caches it.
25
+ *
26
+ * @author Axel Nana <ax.lnana@outlook.com>
27
+ * @param tenant The tenant identifier.
28
+ * @param tableName The table name.
29
+ * @param columns The column definitions.
30
+ * @returns A tenant-scoped `PgTable`.
31
+ * @throws {Error} If the tenant identifier is malformed.
32
+ */
33
+ export declare const wrapTenantSchema: <TTableName extends string, TColumnsMap extends Record<string, AnyPgColumnBuilder>>(tenant: string, tableName: TTableName, columns: TColumnsMap) => PgTable;
34
+ /**
35
+ * Executes a callback within an RLS-scoped transaction for the given tenant.
36
+ *
37
+ * The transaction is registered in the async context, so repositories and
38
+ * `Database.getConnection()` use it inside the callback. When a transaction is already open on the
39
+ * connection, the callback joins it if it is bound to the same tenant. Work for several tenants
40
+ * (such as an admin fan-out) must use one `withRLS()` per tenant, outside any transaction.
41
+ * @author Axel Nana <ax.lnana@outlook.com>
42
+ * @param tenant The tenant identifier (or `null` for 'public').
43
+ * @param callback The function to execute within the transaction.
44
+ * @param connectionName The database connection name.
45
+ * @returns The return value of the callback.
46
+ * @throws {TenantMismatchError} If the open transaction is bound to another tenant.
47
+ */
48
+ export declare const withRLS: <T>(tenant: string | null, callback: (tx: PgAsyncTransaction<any, any>) => Promise<T>, connectionName?: string) => Promise<T>;
49
+ /**
50
+ * Reads the current tenant from the PostgreSQL tenant variable, on the open transaction when
51
+ * there is one.
52
+ * @author Axel Nana <ax.lnana@outlook.com>
53
+ * @param connectionName The database connection name.
54
+ * @returns The current tenant identifier, or `null`.
55
+ */
56
+ export declare const getSessionTenant: (connectionName?: string) => Promise<string | null>;
57
+ /**
58
+ * Creates an RLS policy for tenant isolation on a table.
59
+ * @author Axel Nana <ax.lnana@outlook.com>
60
+ * @param tableName The table name.
61
+ * @param columnName The tenant column name (defaults to config or 'tenant_id').
62
+ * @param policyName The policy name (defaults to `{tableName}_tenant_isolation`).
63
+ * @returns A Drizzle `PgPolicy` instance.
64
+ */
65
+ export declare const createRLSPolicy: (tableName: string, columnName?: string, policyName?: string) => import("drizzle-orm/pg-core").PgPolicy;
66
+ /**
67
+ * Schema-based tenancy strategy for Drizzle.
68
+ *
69
+ * Each tenant gets its own PostgreSQL schema. Table resolution maps
70
+ * the base table to a schema-qualified equivalent.
71
+ *
72
+ * @author Axel Nana <ax.lnana@outlook.com>
73
+ */
74
+ export declare class DrizzleSchemaTenancy implements TenancyStrategy<PgTable, DrizzleConnection> {
75
+ readonly mode = "schema";
76
+ resolveTable(table: PgTable, tenant: string): PgTable;
77
+ withIsolation<T>(_connection: DrizzleConnection, _tenant: string, callback: () => Promise<T>): Promise<T>;
78
+ }
79
+ /**
80
+ * Row-Level Security tenancy strategy for Drizzle.
81
+ *
82
+ * All tenants share the same schema. Isolation is achieved via
83
+ * PostgreSQL RLS policies and a session variable set in each transaction.
84
+ *
85
+ * @author Axel Nana <ax.lnana@outlook.com>
86
+ */
87
+ export declare class DrizzleRLSTenancy implements TenancyStrategy<PgTable, DrizzleConnection> {
88
+ readonly mode = "rls";
89
+ resolveTable(table: PgTable, _tenant: string): PgTable;
90
+ /**
91
+ * Runs a callback in a transaction scoped to the given tenant.
92
+ *
93
+ * The transaction is bound to the tenant for its whole life, registered in the async context
94
+ * for the connection, and the tenant set as the current tenant, for the duration of the
95
+ * callback. When a transaction is already open on the connection, the callback joins it, which
96
+ * is only allowed when that transaction is bound to the same tenant.
97
+ * @author Axel Nana <ax.lnana@outlook.com>
98
+ * @param connection The base connection (see `Database.getBaseConnection`).
99
+ * @param tenant The tenant identifier.
100
+ * @param callback The function to execute within the isolated context.
101
+ * @returns The return value of the callback.
102
+ * @throws {TenantMismatchError} If the open transaction is bound to another tenant.
103
+ */
104
+ withIsolation<T>(connection: DrizzleConnection, tenant: string, callback: () => Promise<T>): Promise<T>;
105
+ }