arkormx 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +53 -7
- package/dist/{index-CpZK_wI9.d.cts → index-C77nMASp.d.mts} +437 -5
- package/dist/{index-DjiQjqkW.d.mts → index-Dnn0lsDy.d.cts} +437 -5
- package/dist/index.cjs +729 -5
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +729 -6
- package/dist/relationship/index.cjs +1 -1
- package/dist/relationship/index.d.cts +1 -1
- package/dist/relationship/index.d.mts +1 -1
- package/dist/relationship/index.mjs +1 -1
- package/dist/{relationship-D9u7BlWh.cjs → relationship-B8FaJYIx.cjs} +135 -7
- package/dist/{relationship-C5hos4aH.mjs → relationship-BuwKUTOb.mjs} +135 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_relationship = require('./relationship-
|
|
2
|
+
const require_relationship = require('./relationship-B8FaJYIx.cjs');
|
|
3
3
|
let pg = require("pg");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
let module$1 = require("module");
|
|
@@ -64,7 +64,8 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
64
64
|
rawSelect: true,
|
|
65
65
|
rawWhere: true,
|
|
66
66
|
distinct: true,
|
|
67
|
-
groupBy: true
|
|
67
|
+
groupBy: true,
|
|
68
|
+
joins: true
|
|
68
69
|
};
|
|
69
70
|
}
|
|
70
71
|
resolveConfiguredDatabaseName(connectionString) {
|
|
@@ -89,6 +90,85 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
89
90
|
quoteIdentifier(value) {
|
|
90
91
|
return `"${value.replace(/"/g, "\"\"")}"`;
|
|
91
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Wraps bare camelCase identifiers in a fragment of raw SQL with double quotes
|
|
95
|
+
* so PostgreSQL preserves their casing instead of folding them to lower case.
|
|
96
|
+
*
|
|
97
|
+
* Identifiers that are already quoted, string literals, dollar-quoted bodies,
|
|
98
|
+
* comments and function names (a camelCase token immediately followed by `(`)
|
|
99
|
+
* are left untouched. Lower-case identifiers are also left alone since
|
|
100
|
+
* PostgreSQL folds them to the same value with or without quotes.
|
|
101
|
+
*
|
|
102
|
+
* @param sql The raw SQL fragment to normalize.
|
|
103
|
+
* @returns
|
|
104
|
+
*/
|
|
105
|
+
quoteCamelCaseIdentifiers(sql) {
|
|
106
|
+
let result = "";
|
|
107
|
+
let index = 0;
|
|
108
|
+
const isIdentifierStart = (char) => /[A-Za-z_]/.test(char);
|
|
109
|
+
const isIdentifierPart = (char) => /[A-Za-z0-9_$]/.test(char);
|
|
110
|
+
const isMixedCase = (token) => /[A-Z]/.test(token) && /[a-z]/.test(token);
|
|
111
|
+
while (index < sql.length) {
|
|
112
|
+
const char = sql[index];
|
|
113
|
+
if (char === "'") {
|
|
114
|
+
const start = index;
|
|
115
|
+
index += 1;
|
|
116
|
+
while (index < sql.length) {
|
|
117
|
+
if (sql[index] === "'" && sql[index + 1] === "'") {
|
|
118
|
+
index += 2;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (sql[index] === "'") {
|
|
122
|
+
index += 1;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
index += 1;
|
|
126
|
+
}
|
|
127
|
+
result += sql.slice(start, index);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (char === "\"") {
|
|
131
|
+
const start = index;
|
|
132
|
+
index += 1;
|
|
133
|
+
while (index < sql.length) {
|
|
134
|
+
if (sql[index] === "\"" && sql[index + 1] === "\"") {
|
|
135
|
+
index += 2;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (sql[index] === "\"") {
|
|
139
|
+
index += 1;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
index += 1;
|
|
143
|
+
}
|
|
144
|
+
result += sql.slice(start, index);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (char === "$") {
|
|
148
|
+
const tagMatch = /^\$[A-Za-z0-9_]*\$/.exec(sql.slice(index));
|
|
149
|
+
if (tagMatch) {
|
|
150
|
+
const tag = tagMatch[0];
|
|
151
|
+
const closeIndex = sql.indexOf(tag, index + tag.length);
|
|
152
|
+
const end = closeIndex === -1 ? sql.length : closeIndex + tag.length;
|
|
153
|
+
result += sql.slice(index, end);
|
|
154
|
+
index = end;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (isIdentifierStart(char)) {
|
|
159
|
+
const start = index;
|
|
160
|
+
while (index < sql.length && isIdentifierPart(sql[index])) index += 1;
|
|
161
|
+
const token = sql.slice(start, index);
|
|
162
|
+
const isFunctionCall = sql[index] === "(";
|
|
163
|
+
if (isMixedCase(token) && !isFunctionCall) result += this.quoteIdentifier(token);
|
|
164
|
+
else result += token;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
result += char;
|
|
168
|
+
index += 1;
|
|
169
|
+
}
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
92
172
|
quoteLiteral(value) {
|
|
93
173
|
if (value == null) return "null";
|
|
94
174
|
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
@@ -108,10 +188,102 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
108
188
|
async executeRawStatement(statement, executor = this.db) {
|
|
109
189
|
await kysely.sql.raw(statement).execute(executor);
|
|
110
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Splits a SQL script into individual top-level statements.
|
|
193
|
+
*
|
|
194
|
+
* The PostgreSQL wire protocol used by Kysely rejects scripts that contain
|
|
195
|
+
* more than one command, so multi-statement raw SQL (for example a migration
|
|
196
|
+
* that mixes `do $$ ... $$` blocks with `alter table` statements) must be
|
|
197
|
+
* executed one statement at a time. Semicolons inside single-quoted strings,
|
|
198
|
+
* double-quoted identifiers, dollar-quoted bodies and comments are ignored.
|
|
199
|
+
*
|
|
200
|
+
* @param sql The raw SQL script to split.
|
|
201
|
+
* @returns
|
|
202
|
+
*/
|
|
203
|
+
splitSqlStatements(sql) {
|
|
204
|
+
const statements = [];
|
|
205
|
+
let current = "";
|
|
206
|
+
let index = 0;
|
|
207
|
+
while (index < sql.length) {
|
|
208
|
+
const char = sql[index];
|
|
209
|
+
const next = sql[index + 1];
|
|
210
|
+
if (char === "-" && next === "-") {
|
|
211
|
+
const end = sql.indexOf("\n", index);
|
|
212
|
+
const stop = end === -1 ? sql.length : end;
|
|
213
|
+
current += sql.slice(index, stop);
|
|
214
|
+
index = stop;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (char === "/" && next === "*") {
|
|
218
|
+
const end = sql.indexOf("*/", index + 2);
|
|
219
|
+
const stop = end === -1 ? sql.length : end + 2;
|
|
220
|
+
current += sql.slice(index, stop);
|
|
221
|
+
index = stop;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (char === "'") {
|
|
225
|
+
const start = index;
|
|
226
|
+
index += 1;
|
|
227
|
+
while (index < sql.length) {
|
|
228
|
+
if (sql[index] === "'" && sql[index + 1] === "'") {
|
|
229
|
+
index += 2;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (sql[index] === "'") {
|
|
233
|
+
index += 1;
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
index += 1;
|
|
237
|
+
}
|
|
238
|
+
current += sql.slice(start, index);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (char === "\"") {
|
|
242
|
+
const start = index;
|
|
243
|
+
index += 1;
|
|
244
|
+
while (index < sql.length) {
|
|
245
|
+
if (sql[index] === "\"" && sql[index + 1] === "\"") {
|
|
246
|
+
index += 2;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (sql[index] === "\"") {
|
|
250
|
+
index += 1;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
index += 1;
|
|
254
|
+
}
|
|
255
|
+
current += sql.slice(start, index);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (char === "$") {
|
|
259
|
+
const tagMatch = /^\$[A-Za-z0-9_]*\$/.exec(sql.slice(index));
|
|
260
|
+
if (tagMatch) {
|
|
261
|
+
const tag = tagMatch[0];
|
|
262
|
+
const closeIndex = sql.indexOf(tag, index + tag.length);
|
|
263
|
+
const end = closeIndex === -1 ? sql.length : closeIndex + tag.length;
|
|
264
|
+
current += sql.slice(index, end);
|
|
265
|
+
index = end;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (char === ";") {
|
|
270
|
+
if (current.trim().length > 0) statements.push(current.trim());
|
|
271
|
+
current = "";
|
|
272
|
+
index += 1;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
current += char;
|
|
276
|
+
index += 1;
|
|
277
|
+
}
|
|
278
|
+
if (current.trim().length > 0) statements.push(current.trim());
|
|
279
|
+
return statements;
|
|
280
|
+
}
|
|
111
281
|
async rawQuery(spec) {
|
|
112
282
|
const statement = this.interpolateRawSql(spec.sql, spec.bindings);
|
|
283
|
+
const statements = this.splitSqlStatements(statement);
|
|
284
|
+
if (statements.length > 1) return await this.runMultiStatementRawQuery(statements, statement);
|
|
113
285
|
try {
|
|
114
|
-
return (await kysely.sql.raw(statement).execute(this.db)).rows ?? [];
|
|
286
|
+
return (await kysely.sql.raw(statements[0] ?? statement).execute(this.db)).rows ?? [];
|
|
115
287
|
} catch (error) {
|
|
116
288
|
throw new QueryExecutionException("Raw query execution failed for the Kysely adapter.", {
|
|
117
289
|
code: "QUERY_EXECUTION_FAILED",
|
|
@@ -123,6 +295,45 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
123
295
|
});
|
|
124
296
|
}
|
|
125
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Executes a multi-statement raw SQL script one statement at a time.
|
|
300
|
+
*
|
|
301
|
+
* Each statement is sent individually so the PostgreSQL extended protocol
|
|
302
|
+
* accepts it, and the rows of the last statement that returns any are used as
|
|
303
|
+
* the result. The script is wrapped in a transaction when the adapter is not
|
|
304
|
+
* already operating inside one so partial failures do not leave the database
|
|
305
|
+
* in a half-applied state.
|
|
306
|
+
*
|
|
307
|
+
* @param statements The individual statements to execute in order.
|
|
308
|
+
* @param fullScript The original (joined) script, used for error context.
|
|
309
|
+
* @returns
|
|
310
|
+
*/
|
|
311
|
+
async runMultiStatementRawQuery(statements, fullScript) {
|
|
312
|
+
const execute = async (executor) => {
|
|
313
|
+
let rows = [];
|
|
314
|
+
for (const statement of statements) {
|
|
315
|
+
const result = await kysely.sql.raw(statement).execute(executor);
|
|
316
|
+
if (result.rows && result.rows.length > 0) rows = result.rows;
|
|
317
|
+
}
|
|
318
|
+
return rows;
|
|
319
|
+
};
|
|
320
|
+
try {
|
|
321
|
+
if (!this.db.isTransaction) return await this.db.transaction().execute((transaction) => execute(transaction));
|
|
322
|
+
return await execute(this.db);
|
|
323
|
+
} catch (error) {
|
|
324
|
+
throw new QueryExecutionException("Raw query execution failed for the Kysely adapter.", {
|
|
325
|
+
code: "QUERY_EXECUTION_FAILED",
|
|
326
|
+
operation: "adapter.rawQuery",
|
|
327
|
+
delegate: "raw",
|
|
328
|
+
inspection: this.tryInspectRawQuery(fullScript),
|
|
329
|
+
meta: {
|
|
330
|
+
sql: fullScript,
|
|
331
|
+
statements
|
|
332
|
+
},
|
|
333
|
+
cause: error
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
126
337
|
tryInspectRawQuery(statement) {
|
|
127
338
|
return {
|
|
128
339
|
adapter: "kysely",
|
|
@@ -404,6 +615,70 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
404
615
|
if (!groupBy || groupBy.length === 0) return kysely.sql``;
|
|
405
616
|
return kysely.sql` group by ${kysely.sql.join(groupBy.map((column) => kysely.sql.ref(this.mapColumn(target, column))), kysely.sql`, `)}`;
|
|
406
617
|
}
|
|
618
|
+
buildJoinClause(target, joins) {
|
|
619
|
+
if (!joins || joins.length === 0) return kysely.sql``;
|
|
620
|
+
return kysely.sql` ${kysely.sql.join(joins.map((join) => this.buildSingleJoin(target, join)), kysely.sql` `)}`;
|
|
621
|
+
}
|
|
622
|
+
joinKeyword(join) {
|
|
623
|
+
const base = {
|
|
624
|
+
inner: "inner join",
|
|
625
|
+
left: "left join",
|
|
626
|
+
right: "right join",
|
|
627
|
+
full: "full join",
|
|
628
|
+
cross: "cross join"
|
|
629
|
+
}[join.type];
|
|
630
|
+
return join.lateral ? `${base} lateral` : base;
|
|
631
|
+
}
|
|
632
|
+
buildJoinSource(join) {
|
|
633
|
+
if (join.subquery) {
|
|
634
|
+
const subquery = this.buildSelectStatement(join.subquery);
|
|
635
|
+
return join.alias ? kysely.sql`(${subquery}) as ${kysely.sql.id(join.alias)}` : kysely.sql`(${subquery})`;
|
|
636
|
+
}
|
|
637
|
+
if (join.subquerySql) return join.alias ? kysely.sql`(${kysely.sql.raw(join.subquerySql)}) as ${kysely.sql.id(join.alias)}` : kysely.sql.raw(`(${join.subquerySql})`);
|
|
638
|
+
const table = this.resolveMappedTable(join.table ?? "");
|
|
639
|
+
return join.alias ? kysely.sql`${kysely.sql.table(table)} as ${kysely.sql.id(join.alias)}` : kysely.sql.table(table);
|
|
640
|
+
}
|
|
641
|
+
buildSingleJoin(target, join) {
|
|
642
|
+
const keyword = kysely.sql.raw(this.joinKeyword(join));
|
|
643
|
+
const source = this.buildJoinSource(join);
|
|
644
|
+
if (join.type === "cross") return kysely.sql`${keyword} ${source}`;
|
|
645
|
+
if (join.constraints.length === 0) return join.lateral ? kysely.sql`${keyword} ${source} on true` : kysely.sql`${keyword} ${source}`;
|
|
646
|
+
return kysely.sql`${keyword} ${source} on ${this.buildJoinConstraints(target, join.constraints)}`;
|
|
647
|
+
}
|
|
648
|
+
buildJoinConstraints(target, constraints) {
|
|
649
|
+
const parts = [];
|
|
650
|
+
constraints.forEach((constraint, index) => {
|
|
651
|
+
if (index > 0) parts.push(kysely.sql.raw(` ${constraint.boolean} `));
|
|
652
|
+
parts.push(this.buildJoinConstraint(target, constraint));
|
|
653
|
+
});
|
|
654
|
+
return kysely.sql`${kysely.sql.join(parts, kysely.sql``)}`;
|
|
655
|
+
}
|
|
656
|
+
buildJoinConstraint(target, constraint) {
|
|
657
|
+
if (constraint.type === "column") return kysely.sql`${kysely.sql.ref(constraint.first)} ${kysely.sql.raw(constraint.operator)} ${kysely.sql.ref(constraint.second)}`;
|
|
658
|
+
if (constraint.type === "null") return constraint.not ? kysely.sql`${kysely.sql.ref(constraint.column)} is not null` : kysely.sql`${kysely.sql.ref(constraint.column)} is null`;
|
|
659
|
+
if (constraint.type === "raw") return this.buildRawWhereCondition({
|
|
660
|
+
type: "raw",
|
|
661
|
+
sql: constraint.sql,
|
|
662
|
+
bindings: constraint.bindings
|
|
663
|
+
});
|
|
664
|
+
if (constraint.type === "nested") return kysely.sql`(${this.buildJoinConstraints(target, constraint.constraints)})`;
|
|
665
|
+
const column = kysely.sql.ref(constraint.column);
|
|
666
|
+
const operator = constraint.operator;
|
|
667
|
+
if (operator === "is-null") return kysely.sql`${column} is null`;
|
|
668
|
+
if (operator === "is-not-null") return kysely.sql`${column} is not null`;
|
|
669
|
+
if (operator === "in") {
|
|
670
|
+
const values = this.buildConditionValueList(constraint.value);
|
|
671
|
+
return values.length === 0 ? kysely.sql`1 = 0` : kysely.sql`${column} in (${kysely.sql.join(values)})`;
|
|
672
|
+
}
|
|
673
|
+
if (operator === "not-in") {
|
|
674
|
+
const values = this.buildConditionValueList(constraint.value);
|
|
675
|
+
return values.length === 0 ? kysely.sql`1 = 1` : kysely.sql`${column} not in (${kysely.sql.join(values)})`;
|
|
676
|
+
}
|
|
677
|
+
if (operator === "contains") return kysely.sql`${column} like ${`%${String(constraint.value ?? "")}%`}`;
|
|
678
|
+
if (operator === "starts-with") return kysely.sql`${column} like ${`${String(constraint.value ?? "")}%`}`;
|
|
679
|
+
if (operator === "ends-with") return kysely.sql`${column} like ${`%${String(constraint.value ?? "")}`}`;
|
|
680
|
+
return kysely.sql`${column} ${kysely.sql.raw(operator)} ${constraint.value}`;
|
|
681
|
+
}
|
|
407
682
|
buildConditionValueList(value) {
|
|
408
683
|
if (Array.isArray(value)) return value;
|
|
409
684
|
return typeof value === "undefined" ? [] : [value];
|
|
@@ -433,7 +708,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
433
708
|
if (segments.length !== bindings.length + 1) throw new require_relationship.ArkormException("Raw where bindings do not match the number of placeholders.");
|
|
434
709
|
const parts = [];
|
|
435
710
|
segments.forEach((segment, index) => {
|
|
436
|
-
if (segment.length > 0) parts.push(kysely.sql.raw(segment));
|
|
711
|
+
if (segment.length > 0) parts.push(kysely.sql.raw(this.quoteCamelCaseIdentifiers(segment)));
|
|
437
712
|
if (index < bindings.length) parts.push(kysely.sql`${bindings[index]}`);
|
|
438
713
|
});
|
|
439
714
|
if (parts.length === 0) return kysely.sql`1 = 1`;
|
|
@@ -697,6 +972,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
697
972
|
select ${spec.distinct ? kysely.sql`distinct ` : kysely.sql``}${this.buildSelectList(spec.target, spec.columns)}
|
|
698
973
|
${this.buildRelationAggregateSelectList(spec.target, spec.relationAggregates)}
|
|
699
974
|
from ${kysely.sql.table(this.resolveTable(spec.target))}
|
|
975
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
700
976
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
701
977
|
${this.buildGroupBy(spec.target, spec.groupBy)}
|
|
702
978
|
${this.buildOrderBy(spec.target, spec.orderBy)}
|
|
@@ -707,6 +983,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
707
983
|
return kysely.sql`
|
|
708
984
|
select count(*)::int as count
|
|
709
985
|
from ${kysely.sql.table(this.resolveTable(spec.target))}
|
|
986
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
710
987
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
711
988
|
`;
|
|
712
989
|
}
|
|
@@ -715,6 +992,7 @@ var KyselyDatabaseAdapter = class KyselyDatabaseAdapter {
|
|
|
715
992
|
select exists(
|
|
716
993
|
select 1
|
|
717
994
|
from ${kysely.sql.table(this.resolveTable(spec.target))}
|
|
995
|
+
${this.buildJoinClause(spec.target, spec.joins)}
|
|
718
996
|
${this.buildCombinedWhereClause(spec.target, spec.where, spec.relationFilters)}
|
|
719
997
|
${this.buildGroupBy(spec.target, spec.groupBy)}
|
|
720
998
|
limit 1
|
|
@@ -1446,6 +1724,10 @@ var PrismaDatabaseAdapter = class PrismaDatabaseAdapter {
|
|
|
1446
1724
|
operation: "adapter.select",
|
|
1447
1725
|
meta: { feature: "groupBy" }
|
|
1448
1726
|
});
|
|
1727
|
+
if (spec.joins?.length) throw new require_relationship.UnsupportedAdapterFeatureException("Join clauses are not supported by the Prisma compatibility adapter; use a SQL-backed adapter or DB.raw().", {
|
|
1728
|
+
operation: "adapter.select",
|
|
1729
|
+
meta: { feature: "joins" }
|
|
1730
|
+
});
|
|
1449
1731
|
return {
|
|
1450
1732
|
include: this.toQueryInclude(spec.relationLoads),
|
|
1451
1733
|
where: this.toQueryWhere(spec.where),
|
|
@@ -3800,6 +4082,204 @@ const resolveRuntimeCompatibilityQuerySchemaOrThrow = (key, candidates, modelNam
|
|
|
3800
4082
|
return resolved;
|
|
3801
4083
|
};
|
|
3802
4084
|
|
|
4085
|
+
//#endregion
|
|
4086
|
+
//#region src/JoinClause.ts
|
|
4087
|
+
/**
|
|
4088
|
+
* A fluent builder for the `on`/`where` constraints of a join clause.
|
|
4089
|
+
*
|
|
4090
|
+
* Instances are handed to the closure form of the query builder join helpers
|
|
4091
|
+
* (for example `query.join('posts', join => join.on(...).where(...))`) and
|
|
4092
|
+
* mirror Laravel's `JoinClause` surface. Column identifiers are treated as raw
|
|
4093
|
+
* database identifiers (qualify them as `table.column` when needed).
|
|
4094
|
+
*
|
|
4095
|
+
* @author Legacy (3m1n3nc3)
|
|
4096
|
+
*/
|
|
4097
|
+
var JoinClause = class JoinClause {
|
|
4098
|
+
constructor() {
|
|
4099
|
+
this.constraints = [];
|
|
4100
|
+
}
|
|
4101
|
+
/**
|
|
4102
|
+
* Adds a column-to-column `on` constraint, joined with `and`.
|
|
4103
|
+
*
|
|
4104
|
+
* Accepts either a closure (for a nested group) or a column comparison in
|
|
4105
|
+
* the `(first, second)` or `(first, operator, second)` form.
|
|
4106
|
+
*
|
|
4107
|
+
* @param first The left-hand column or a nested closure.
|
|
4108
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
4109
|
+
* @param second The right-hand column.
|
|
4110
|
+
* @returns
|
|
4111
|
+
*/
|
|
4112
|
+
on(first, operator, second) {
|
|
4113
|
+
return this.addOn("and", first, operator, second);
|
|
4114
|
+
}
|
|
4115
|
+
/**
|
|
4116
|
+
* Adds a column-to-column `on` constraint, joined with `or`.
|
|
4117
|
+
*
|
|
4118
|
+
* @param first The left-hand column or a nested closure.
|
|
4119
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
4120
|
+
* @param second The right-hand column.
|
|
4121
|
+
* @returns
|
|
4122
|
+
*/
|
|
4123
|
+
orOn(first, operator, second) {
|
|
4124
|
+
return this.addOn("or", first, operator, second);
|
|
4125
|
+
}
|
|
4126
|
+
/**
|
|
4127
|
+
* Adds a column-to-value constraint, joined with `and`.
|
|
4128
|
+
*
|
|
4129
|
+
* @param column The column being compared.
|
|
4130
|
+
* @param operator The comparison operator or the value when omitted.
|
|
4131
|
+
* @param value The value to compare against.
|
|
4132
|
+
* @returns
|
|
4133
|
+
*/
|
|
4134
|
+
where(column, operator, value) {
|
|
4135
|
+
return this.addWhere("and", column, operator, value);
|
|
4136
|
+
}
|
|
4137
|
+
/**
|
|
4138
|
+
* Adds a column-to-value constraint, joined with `or`.
|
|
4139
|
+
*
|
|
4140
|
+
* @param column The column being compared.
|
|
4141
|
+
* @param operator The comparison operator or the value when omitted.
|
|
4142
|
+
* @param value The value to compare against.
|
|
4143
|
+
* @returns
|
|
4144
|
+
*/
|
|
4145
|
+
orWhere(column, operator, value) {
|
|
4146
|
+
return this.addWhere("or", column, operator, value);
|
|
4147
|
+
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Adds an `is null` constraint joined with `and`.
|
|
4150
|
+
*
|
|
4151
|
+
* @param column The column to test for null.
|
|
4152
|
+
* @returns
|
|
4153
|
+
*/
|
|
4154
|
+
whereNull(column) {
|
|
4155
|
+
this.constraints.push({
|
|
4156
|
+
type: "null",
|
|
4157
|
+
boolean: "and",
|
|
4158
|
+
column,
|
|
4159
|
+
not: false
|
|
4160
|
+
});
|
|
4161
|
+
return this;
|
|
4162
|
+
}
|
|
4163
|
+
/**
|
|
4164
|
+
* Adds an `is null` constraint joined with `or`.
|
|
4165
|
+
*
|
|
4166
|
+
* @param column The column to test for null.
|
|
4167
|
+
* @returns
|
|
4168
|
+
*/
|
|
4169
|
+
orWhereNull(column) {
|
|
4170
|
+
this.constraints.push({
|
|
4171
|
+
type: "null",
|
|
4172
|
+
boolean: "or",
|
|
4173
|
+
column,
|
|
4174
|
+
not: false
|
|
4175
|
+
});
|
|
4176
|
+
return this;
|
|
4177
|
+
}
|
|
4178
|
+
/**
|
|
4179
|
+
* Adds an `is not null` constraint joined with `and`.
|
|
4180
|
+
*
|
|
4181
|
+
* @param column The column to test for non-null.
|
|
4182
|
+
* @returns
|
|
4183
|
+
*/
|
|
4184
|
+
whereNotNull(column) {
|
|
4185
|
+
this.constraints.push({
|
|
4186
|
+
type: "null",
|
|
4187
|
+
boolean: "and",
|
|
4188
|
+
column,
|
|
4189
|
+
not: true
|
|
4190
|
+
});
|
|
4191
|
+
return this;
|
|
4192
|
+
}
|
|
4193
|
+
/**
|
|
4194
|
+
* Adds an `is not null` constraint joined with `or`.
|
|
4195
|
+
*
|
|
4196
|
+
* @param column The column to test for non-null.
|
|
4197
|
+
* @returns
|
|
4198
|
+
*/
|
|
4199
|
+
orWhereNotNull(column) {
|
|
4200
|
+
this.constraints.push({
|
|
4201
|
+
type: "null",
|
|
4202
|
+
boolean: "or",
|
|
4203
|
+
column,
|
|
4204
|
+
not: true
|
|
4205
|
+
});
|
|
4206
|
+
return this;
|
|
4207
|
+
}
|
|
4208
|
+
/**
|
|
4209
|
+
* Adds a raw constraint joined with `and`.
|
|
4210
|
+
*
|
|
4211
|
+
* @param sql The raw SQL fragment (with `?` placeholders for bindings).
|
|
4212
|
+
* @param bindings The values bound to the placeholders.
|
|
4213
|
+
* @returns
|
|
4214
|
+
*/
|
|
4215
|
+
onRaw(sql, bindings = []) {
|
|
4216
|
+
this.constraints.push({
|
|
4217
|
+
type: "raw",
|
|
4218
|
+
boolean: "and",
|
|
4219
|
+
sql,
|
|
4220
|
+
bindings
|
|
4221
|
+
});
|
|
4222
|
+
return this;
|
|
4223
|
+
}
|
|
4224
|
+
/**
|
|
4225
|
+
* Adds a raw constraint joined with `or`.
|
|
4226
|
+
*
|
|
4227
|
+
* @param sql The raw SQL fragment (with `?` placeholders for bindings).
|
|
4228
|
+
* @param bindings The values bound to the placeholders.
|
|
4229
|
+
* @returns
|
|
4230
|
+
*/
|
|
4231
|
+
orOnRaw(sql, bindings = []) {
|
|
4232
|
+
this.constraints.push({
|
|
4233
|
+
type: "raw",
|
|
4234
|
+
boolean: "or",
|
|
4235
|
+
sql,
|
|
4236
|
+
bindings
|
|
4237
|
+
});
|
|
4238
|
+
return this;
|
|
4239
|
+
}
|
|
4240
|
+
/**
|
|
4241
|
+
* Returns the accumulated constraints for this join clause.
|
|
4242
|
+
*
|
|
4243
|
+
* @returns
|
|
4244
|
+
*/
|
|
4245
|
+
getConstraints() {
|
|
4246
|
+
return this.constraints;
|
|
4247
|
+
}
|
|
4248
|
+
addOn(boolean, first, operator, second) {
|
|
4249
|
+
if (typeof first === "function") {
|
|
4250
|
+
const nested = new JoinClause();
|
|
4251
|
+
first(nested);
|
|
4252
|
+
this.constraints.push({
|
|
4253
|
+
type: "nested",
|
|
4254
|
+
boolean,
|
|
4255
|
+
constraints: nested.getConstraints()
|
|
4256
|
+
});
|
|
4257
|
+
return this;
|
|
4258
|
+
}
|
|
4259
|
+
const [resolvedOperator, resolvedSecond] = second === void 0 ? ["=", operator] : [operator, second];
|
|
4260
|
+
if (typeof resolvedSecond !== "string") throw new Error("A join \"on\" constraint requires a second column.");
|
|
4261
|
+
this.constraints.push({
|
|
4262
|
+
type: "column",
|
|
4263
|
+
boolean,
|
|
4264
|
+
first,
|
|
4265
|
+
operator: resolvedOperator ?? "=",
|
|
4266
|
+
second: resolvedSecond
|
|
4267
|
+
});
|
|
4268
|
+
return this;
|
|
4269
|
+
}
|
|
4270
|
+
addWhere(boolean, column, operator, value) {
|
|
4271
|
+
const [resolvedOperator, resolvedValue] = value === void 0 ? ["=", operator] : [operator, value];
|
|
4272
|
+
this.constraints.push({
|
|
4273
|
+
type: "value",
|
|
4274
|
+
boolean,
|
|
4275
|
+
column,
|
|
4276
|
+
operator: resolvedOperator ?? "=",
|
|
4277
|
+
value: resolvedValue
|
|
4278
|
+
});
|
|
4279
|
+
return this;
|
|
4280
|
+
}
|
|
4281
|
+
};
|
|
4282
|
+
|
|
3803
4283
|
//#endregion
|
|
3804
4284
|
//#region src/Exceptions/ModelNotFoundException.ts
|
|
3805
4285
|
/**
|
|
@@ -4771,7 +5251,248 @@ var QueryBuilder = class QueryBuilder {
|
|
|
4771
5251
|
return this;
|
|
4772
5252
|
}
|
|
4773
5253
|
/**
|
|
4774
|
-
* Adds a
|
|
5254
|
+
* Adds a join clause to the query.
|
|
5255
|
+
*
|
|
5256
|
+
* The `first`/`second` arguments are treated as raw database identifiers, so
|
|
5257
|
+
* qualify them as `table.column` when needed. Pass a closure as `first` to
|
|
5258
|
+
* build a compound `on` condition through a {@link JoinClause}.
|
|
5259
|
+
*
|
|
5260
|
+
* @param table The table (or aliased table) to join.
|
|
5261
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5262
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5263
|
+
* @param second The right-hand column.
|
|
5264
|
+
* @param type The join type (defaults to `inner`).
|
|
5265
|
+
* @returns
|
|
5266
|
+
*/
|
|
5267
|
+
join(table, first, operator, second, type = "inner") {
|
|
5268
|
+
return this.addJoin(type, table, first, operator, second);
|
|
5269
|
+
}
|
|
5270
|
+
/**
|
|
5271
|
+
* Adds an inner join clause to the query.
|
|
5272
|
+
*
|
|
5273
|
+
* @param table The table (or aliased table) to join.
|
|
5274
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5275
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5276
|
+
* @param second The right-hand column.
|
|
5277
|
+
* @returns
|
|
5278
|
+
*/
|
|
5279
|
+
innerJoin(table, first, operator, second) {
|
|
5280
|
+
return this.addJoin("inner", table, first, operator, second);
|
|
5281
|
+
}
|
|
5282
|
+
/**
|
|
5283
|
+
* Adds a left join clause to the query.
|
|
5284
|
+
*
|
|
5285
|
+
* @param table The table (or aliased table) to join.
|
|
5286
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5287
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5288
|
+
* @param second The right-hand column.
|
|
5289
|
+
* @returns
|
|
5290
|
+
*/
|
|
5291
|
+
leftJoin(table, first, operator, second) {
|
|
5292
|
+
return this.addJoin("left", table, first, operator, second);
|
|
5293
|
+
}
|
|
5294
|
+
/**
|
|
5295
|
+
* Adds a right join clause to the query.
|
|
5296
|
+
*
|
|
5297
|
+
* @param table The table (or aliased table) to join.
|
|
5298
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5299
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5300
|
+
* @param second The right-hand column.
|
|
5301
|
+
* @returns
|
|
5302
|
+
*/
|
|
5303
|
+
rightJoin(table, first, operator, second) {
|
|
5304
|
+
return this.addJoin("right", table, first, operator, second);
|
|
5305
|
+
}
|
|
5306
|
+
/**
|
|
5307
|
+
* Adds a cross join clause to the query.
|
|
5308
|
+
*
|
|
5309
|
+
* When a `first` column (or closure) is supplied the cross join is promoted
|
|
5310
|
+
* to an inner join with the given constraints, mirroring Laravel's behaviour.
|
|
5311
|
+
*
|
|
5312
|
+
* @param table The table (or aliased table) to join.
|
|
5313
|
+
* @param first Optional column or closure to constrain the join.
|
|
5314
|
+
* @returns
|
|
5315
|
+
*/
|
|
5316
|
+
crossJoin(table, first) {
|
|
5317
|
+
if (first === void 0) return this.addJoin("cross", table);
|
|
5318
|
+
return this.addJoin("inner", table, first);
|
|
5319
|
+
}
|
|
5320
|
+
/**
|
|
5321
|
+
* Adds a join clause that compares a column to a value.
|
|
5322
|
+
*
|
|
5323
|
+
* @param table The table (or aliased table) to join.
|
|
5324
|
+
* @param first The column being compared.
|
|
5325
|
+
* @param operator The comparison operator.
|
|
5326
|
+
* @param value The value to compare against.
|
|
5327
|
+
* @param type The join type (defaults to `inner`).
|
|
5328
|
+
* @returns
|
|
5329
|
+
*/
|
|
5330
|
+
joinWhere(table, first, operator, value, type = "inner") {
|
|
5331
|
+
return this.addJoinWhere(type, table, first, operator, value);
|
|
5332
|
+
}
|
|
5333
|
+
/**
|
|
5334
|
+
* Adds a left join clause that compares a column to a value.
|
|
5335
|
+
*
|
|
5336
|
+
* @param table The table (or aliased table) to join.
|
|
5337
|
+
* @param first The column being compared.
|
|
5338
|
+
* @param operator The comparison operator.
|
|
5339
|
+
* @param value The value to compare against.
|
|
5340
|
+
* @returns
|
|
5341
|
+
*/
|
|
5342
|
+
leftJoinWhere(table, first, operator, value) {
|
|
5343
|
+
return this.addJoinWhere("left", table, first, operator, value);
|
|
5344
|
+
}
|
|
5345
|
+
/**
|
|
5346
|
+
* Adds a right join clause that compares a column to a value.
|
|
5347
|
+
*
|
|
5348
|
+
* @param table The table (or aliased table) to join.
|
|
5349
|
+
* @param first The column being compared.
|
|
5350
|
+
* @param operator The comparison operator.
|
|
5351
|
+
* @param value The value to compare against.
|
|
5352
|
+
* @returns
|
|
5353
|
+
*/
|
|
5354
|
+
rightJoinWhere(table, first, operator, value) {
|
|
5355
|
+
return this.addJoinWhere("right", table, first, operator, value);
|
|
5356
|
+
}
|
|
5357
|
+
/**
|
|
5358
|
+
* Adds a subquery join clause to the query.
|
|
5359
|
+
*
|
|
5360
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5361
|
+
* @param alias The alias assigned to the subquery.
|
|
5362
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5363
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5364
|
+
* @param second The right-hand column.
|
|
5365
|
+
* @param type The join type (defaults to `inner`).
|
|
5366
|
+
* @returns
|
|
5367
|
+
*/
|
|
5368
|
+
joinSub(query, alias, first, operator, second, type = "inner") {
|
|
5369
|
+
return this.addJoinSub(type, query, alias, first, operator, second);
|
|
5370
|
+
}
|
|
5371
|
+
/**
|
|
5372
|
+
* Adds a subquery left join clause to the query.
|
|
5373
|
+
*
|
|
5374
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5375
|
+
* @param alias The alias assigned to the subquery.
|
|
5376
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5377
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5378
|
+
* @param second The right-hand column.
|
|
5379
|
+
* @returns
|
|
5380
|
+
*/
|
|
5381
|
+
leftJoinSub(query, alias, first, operator, second) {
|
|
5382
|
+
return this.addJoinSub("left", query, alias, first, operator, second);
|
|
5383
|
+
}
|
|
5384
|
+
/**
|
|
5385
|
+
* Adds a subquery right join clause to the query.
|
|
5386
|
+
*
|
|
5387
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5388
|
+
* @param alias The alias assigned to the subquery.
|
|
5389
|
+
* @param first The left-hand column or a closure receiving a JoinClause.
|
|
5390
|
+
* @param operator The comparison operator (defaults to `=`).
|
|
5391
|
+
* @param second The right-hand column.
|
|
5392
|
+
* @returns
|
|
5393
|
+
*/
|
|
5394
|
+
rightJoinSub(query, alias, first, operator, second) {
|
|
5395
|
+
return this.addJoinSub("right", query, alias, first, operator, second);
|
|
5396
|
+
}
|
|
5397
|
+
/**
|
|
5398
|
+
* Adds a cross subquery join clause to the query.
|
|
5399
|
+
*
|
|
5400
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5401
|
+
* @param alias The alias assigned to the subquery.
|
|
5402
|
+
* @returns
|
|
5403
|
+
*/
|
|
5404
|
+
crossJoinSub(query, alias) {
|
|
5405
|
+
return this.addJoinSub("cross", query, alias);
|
|
5406
|
+
}
|
|
5407
|
+
/**
|
|
5408
|
+
* Adds a lateral join clause to the query.
|
|
5409
|
+
*
|
|
5410
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5411
|
+
* @param alias The alias assigned to the subquery.
|
|
5412
|
+
* @param type The join type (defaults to `inner`).
|
|
5413
|
+
* @returns
|
|
5414
|
+
*/
|
|
5415
|
+
joinLateral(query, alias, type = "inner") {
|
|
5416
|
+
return this.addJoinSub(type, query, alias, void 0, void 0, void 0, true);
|
|
5417
|
+
}
|
|
5418
|
+
/**
|
|
5419
|
+
* Adds a lateral left join clause to the query.
|
|
5420
|
+
*
|
|
5421
|
+
* @param query The subquery (a QueryBuilder instance or raw SQL string).
|
|
5422
|
+
* @param alias The alias assigned to the subquery.
|
|
5423
|
+
* @returns
|
|
5424
|
+
*/
|
|
5425
|
+
leftJoinLateral(query, alias) {
|
|
5426
|
+
return this.addJoinSub("left", query, alias, void 0, void 0, void 0, true);
|
|
5427
|
+
}
|
|
5428
|
+
/**
|
|
5429
|
+
* Builds a self-contained select specification used when this query is joined
|
|
5430
|
+
* as a subquery by another query builder.
|
|
5431
|
+
*
|
|
5432
|
+
* @returns
|
|
5433
|
+
*/
|
|
5434
|
+
buildJoinSubquerySpec() {
|
|
5435
|
+
const spec = this.tryBuildSelectSpec(this.buildWhere());
|
|
5436
|
+
if (!spec) throw new require_relationship.UnsupportedAdapterFeatureException("Subquery join could not be compiled into an Arkorm select specification.", {
|
|
5437
|
+
operation: "query.joinSub",
|
|
5438
|
+
model: this.model.name
|
|
5439
|
+
});
|
|
5440
|
+
return spec;
|
|
5441
|
+
}
|
|
5442
|
+
guardJoinSupport() {
|
|
5443
|
+
if (!this.adapter?.capabilities?.joins) throw new require_relationship.UnsupportedAdapterFeatureException("Join clauses are not supported by the current adapter.", {
|
|
5444
|
+
operation: "join",
|
|
5445
|
+
model: this.model.name,
|
|
5446
|
+
meta: { feature: "joins" }
|
|
5447
|
+
});
|
|
5448
|
+
}
|
|
5449
|
+
pushJoin(join) {
|
|
5450
|
+
(this.queryJoins ??= []).push(join);
|
|
5451
|
+
}
|
|
5452
|
+
resolveJoinConstraints(first, operator, second) {
|
|
5453
|
+
if (first === void 0) return [];
|
|
5454
|
+
const clause = new JoinClause();
|
|
5455
|
+
if (typeof first === "function") first(clause);
|
|
5456
|
+
else clause.on(first, operator, second);
|
|
5457
|
+
return clause.getConstraints();
|
|
5458
|
+
}
|
|
5459
|
+
resolveJoinSource(query) {
|
|
5460
|
+
if (typeof query === "string") return { subquerySql: query };
|
|
5461
|
+
return { subquery: query.buildJoinSubquerySpec() };
|
|
5462
|
+
}
|
|
5463
|
+
addJoin(type, table, first, operator, second) {
|
|
5464
|
+
this.guardJoinSupport();
|
|
5465
|
+
this.pushJoin({
|
|
5466
|
+
type,
|
|
5467
|
+
table,
|
|
5468
|
+
constraints: this.resolveJoinConstraints(first, operator, second)
|
|
5469
|
+
});
|
|
5470
|
+
return this;
|
|
5471
|
+
}
|
|
5472
|
+
addJoinWhere(type, table, column, operator, value) {
|
|
5473
|
+
this.guardJoinSupport();
|
|
5474
|
+
const clause = new JoinClause();
|
|
5475
|
+
clause.where(column, operator, value);
|
|
5476
|
+
this.pushJoin({
|
|
5477
|
+
type,
|
|
5478
|
+
table,
|
|
5479
|
+
constraints: clause.getConstraints()
|
|
5480
|
+
});
|
|
5481
|
+
return this;
|
|
5482
|
+
}
|
|
5483
|
+
addJoinSub(type, query, alias, first, operator, second, lateral = false) {
|
|
5484
|
+
this.guardJoinSupport();
|
|
5485
|
+
this.pushJoin({
|
|
5486
|
+
type,
|
|
5487
|
+
alias,
|
|
5488
|
+
...this.resolveJoinSource(query),
|
|
5489
|
+
...lateral ? { lateral: true } : {},
|
|
5490
|
+
constraints: this.resolveJoinConstraints(first, operator, second)
|
|
5491
|
+
});
|
|
5492
|
+
return this;
|
|
5493
|
+
}
|
|
5494
|
+
/**
|
|
5495
|
+
* Adds a skip clause to the query for pagination.
|
|
4775
5496
|
* This will overwrite any existing skip clause.
|
|
4776
5497
|
*
|
|
4777
5498
|
* @param skip
|
|
@@ -6026,6 +6747,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
6026
6747
|
columns,
|
|
6027
6748
|
distinct: this.queryDistinct || void 0,
|
|
6028
6749
|
groupBy: this.queryGroupBy ? [...this.queryGroupBy] : void 0,
|
|
6750
|
+
joins: this.queryJoins ? [...this.queryJoins] : void 0,
|
|
6029
6751
|
where: condition,
|
|
6030
6752
|
orderBy,
|
|
6031
6753
|
limit: this.limitValue,
|
|
@@ -6042,6 +6764,7 @@ var QueryBuilder = class QueryBuilder {
|
|
|
6042
6764
|
if (this.hasRelationFilters() && this.canExecuteRelationFiltersInAdapter() && relationFilters === null) return null;
|
|
6043
6765
|
return {
|
|
6044
6766
|
target: this.buildQueryTarget(),
|
|
6767
|
+
joins: this.queryJoins ? [...this.queryJoins] : void 0,
|
|
6045
6768
|
where: condition,
|
|
6046
6769
|
relationFilters: this.canExecuteRelationFiltersInAdapter() ? relationFilters ?? void 0 : void 0,
|
|
6047
6770
|
aggregate: { type: "count" }
|
|
@@ -8366,6 +9089,7 @@ exports.EnumBuilder = require_relationship.EnumBuilder;
|
|
|
8366
9089
|
exports.ForeignKeyBuilder = require_relationship.ForeignKeyBuilder;
|
|
8367
9090
|
exports.InitCommand = InitCommand;
|
|
8368
9091
|
exports.InlineFactory = InlineFactory;
|
|
9092
|
+
exports.JoinClause = JoinClause;
|
|
8369
9093
|
exports.KyselyDatabaseAdapter = KyselyDatabaseAdapter;
|
|
8370
9094
|
exports.LengthAwarePaginator = require_relationship.LengthAwarePaginator;
|
|
8371
9095
|
exports.MIGRATION_BRAND = MIGRATION_BRAND;
|