relq 1.0.86 → 1.0.88

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.
@@ -25,7 +25,12 @@ function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
25
25
  const rightProxy = (0, table_proxy_1.createTableProxy)(rightTableName, rightAlias, rightTableDef);
26
26
  const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
27
27
  if (callback) {
28
- callback(conditionBuilder, leftProxy, rightProxy);
28
+ if (joinType === 'RIGHT JOIN') {
29
+ callback(conditionBuilder, leftProxy, rightProxy);
30
+ }
31
+ else {
32
+ callback(conditionBuilder, rightProxy, leftProxy);
33
+ }
29
34
  }
30
35
  const conditionInternals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
31
36
  if (!conditionInternals.hasConditions() && schema && relations) {
@@ -37,7 +42,7 @@ function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
37
42
  }
38
43
  else {
39
44
  throw new relq_errors_1.RelqQueryError(`Cannot auto-resolve FK relationship between "${ctx.schemaKey || ctx.tableName}" and "${rightTableKey}". ` +
40
- `Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, left, right) => on.equal(left.columnName, right.id))` });
45
+ `Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, ${rightTableKey}, source) => on.equal(${rightTableKey}.id, source.columnName))` });
41
46
  }
42
47
  }
43
48
  const selectedProps = conditionInternals.getSelectedColumns();
@@ -93,7 +98,7 @@ function executeTypeSafeJoinMany(ctx, joinType, tableOrAlias, callback) {
93
98
  };
94
99
  };
95
100
  conditionBuilder[join_internals_1.JOIN_SETUP](proxyCreator, rightProxy);
96
- callback(conditionBuilder, leftProxy, rightProxy);
101
+ callback(conditionBuilder, rightProxy, leftProxy);
97
102
  const lateralSQL = buildLateralSubquery(rightTableName, rightAlias, conditionBuilder, rightTableDef);
98
103
  const lateralJoinType = joinType === 'LEFT JOIN' ? 'LEFT JOIN LATERAL' : 'JOIN LATERAL';
99
104
  const joinClause = {
@@ -113,12 +118,21 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
113
118
  const internals = builder[join_internals_1.JOIN_INTERNAL];
114
119
  parts.push('SELECT');
115
120
  const selectedProps = internals.getSelectedColumns();
121
+ const innerJoins = internals.getInnerJoins();
122
+ const hasInnerJoins = innerJoins.length > 0;
123
+ const toSnake = (s) => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`);
116
124
  if (selectedProps && selectedProps.length > 0) {
117
125
  const tableColumns = tableDef?.$columns || tableDef;
118
126
  const selectCols = selectedProps.map(prop => {
119
127
  const columnDef = tableColumns?.[prop];
120
- const sqlName = columnDef?.$columnName || prop;
121
- return `"${alias}"."${sqlName}" AS "${prop}"`;
128
+ if (columnDef || !hasInnerJoins) {
129
+ const sqlName = columnDef?.$columnName || toSnake(prop);
130
+ return `"${alias}"."${sqlName}" AS "${prop}"`;
131
+ }
132
+ else {
133
+ const sqlName = toSnake(prop);
134
+ return `"${sqlName}" AS "${prop}"`;
135
+ }
122
136
  }).join(', ');
123
137
  parts.push(selectCols);
124
138
  }
@@ -126,7 +140,6 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
126
140
  parts.push(`"${alias}".*`);
127
141
  }
128
142
  parts.push(`FROM "${tableName}" AS "${alias}"`);
129
- const innerJoins = internals.getInnerJoins();
130
143
  for (const join of innerJoins) {
131
144
  parts.push(`${join.type} "${join.table}" AS "${join.alias}" ON ${join.onClause}`);
132
145
  }
@@ -98,12 +98,12 @@ class JoinConditionBuilder {
98
98
  this.whereConditions.push(...collector.getConditions());
99
99
  return this;
100
100
  }
101
- select(columns) {
102
- if (columns === '*') {
103
- this.selectedColumns = undefined;
101
+ select(...args) {
102
+ if (args.length === 1 && Array.isArray(args[0])) {
103
+ this.selectedColumns = args[0];
104
104
  }
105
105
  else {
106
- this.selectedColumns = columns;
106
+ this.selectedColumns = args;
107
107
  }
108
108
  return this;
109
109
  }
@@ -34,28 +34,34 @@ class JoinManyConditionBuilder extends join_condition_builder_1.JoinConditionBui
34
34
  this.rightProxy = rightProxy;
35
35
  };
36
36
  }
37
- innerJoin(table, callback) {
37
+ innerJoin(tableOrAlias, callback) {
38
38
  if (!this.proxyCreator) {
39
39
  throw new Error('innerJoin requires proxy creator - use raw innerJoinRaw() instead');
40
40
  }
41
- const { proxy: innerProxy, tableName } = this.proxyCreator(table, table);
41
+ const [tableKey, alias] = Array.isArray(tableOrAlias)
42
+ ? tableOrAlias
43
+ : [tableOrAlias, tableOrAlias];
44
+ const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
42
45
  const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
43
46
  callback(conditionBuilder, innerProxy);
44
47
  const internals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
45
48
  const onClause = internals.toSQL();
46
- this.innerJoins.push({ type: 'JOIN', table: tableName, alias: table, onClause });
49
+ this.innerJoins.push({ type: 'JOIN', table: tableName, alias, onClause });
47
50
  return this;
48
51
  }
49
- leftInnerJoin(table, callback) {
52
+ leftInnerJoin(tableOrAlias, callback) {
50
53
  if (!this.proxyCreator) {
51
54
  throw new Error('leftInnerJoin requires proxy creator - use raw leftInnerJoinRaw() instead');
52
55
  }
53
- const { proxy: innerProxy, tableName } = this.proxyCreator(table, table);
56
+ const [tableKey, alias] = Array.isArray(tableOrAlias)
57
+ ? tableOrAlias
58
+ : [tableOrAlias, tableOrAlias];
59
+ const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
54
60
  const conditionBuilder = new join_condition_builder_1.JoinConditionBuilder();
55
61
  callback(conditionBuilder, innerProxy);
56
62
  const internals = conditionBuilder[join_internals_1.JOIN_INTERNAL];
57
63
  const onClause = internals.toSQL();
58
- this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias: table, onClause });
64
+ this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias, onClause });
59
65
  return this;
60
66
  }
61
67
  innerJoinRaw(table, alias, onClause) {
@@ -66,12 +72,12 @@ class JoinManyConditionBuilder extends join_condition_builder_1.JoinConditionBui
66
72
  this.innerJoins.push({ type: 'LEFT JOIN', table, alias, onClause });
67
73
  return this;
68
74
  }
69
- select(columns) {
70
- if (columns === '*') {
71
- this.selectedColumns = undefined;
75
+ select(...args) {
76
+ if (args.length === 1 && Array.isArray(args[0])) {
77
+ this.selectedColumns = args[0];
72
78
  }
73
79
  else {
74
- this.selectedColumns = columns;
80
+ this.selectedColumns = args;
75
81
  }
76
82
  return this;
77
83
  }
@@ -21,7 +21,12 @@ export function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
21
21
  const rightProxy = createTableProxy(rightTableName, rightAlias, rightTableDef);
22
22
  const conditionBuilder = new JoinConditionBuilder();
23
23
  if (callback) {
24
- callback(conditionBuilder, leftProxy, rightProxy);
24
+ if (joinType === 'RIGHT JOIN') {
25
+ callback(conditionBuilder, leftProxy, rightProxy);
26
+ }
27
+ else {
28
+ callback(conditionBuilder, rightProxy, leftProxy);
29
+ }
25
30
  }
26
31
  const conditionInternals = conditionBuilder[JOIN_INTERNAL];
27
32
  if (!conditionInternals.hasConditions() && schema && relations) {
@@ -33,7 +38,7 @@ export function executeTypeSafeJoin(ctx, joinType, tableOrAlias, callback) {
33
38
  }
34
39
  else {
35
40
  throw new RelqQueryError(`Cannot auto-resolve FK relationship between "${ctx.schemaKey || ctx.tableName}" and "${rightTableKey}". ` +
36
- `Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, left, right) => on.equal(left.columnName, right.id))` });
41
+ `Either provide a callback with explicit join conditions, or define the relationship in your relations config.`, { hint: `Use .join('${rightTableKey}', (on, ${rightTableKey}, source) => on.equal(${rightTableKey}.id, source.columnName))` });
37
42
  }
38
43
  }
39
44
  const selectedProps = conditionInternals.getSelectedColumns();
@@ -89,7 +94,7 @@ export function executeTypeSafeJoinMany(ctx, joinType, tableOrAlias, callback) {
89
94
  };
90
95
  };
91
96
  conditionBuilder[JOIN_SETUP](proxyCreator, rightProxy);
92
- callback(conditionBuilder, leftProxy, rightProxy);
97
+ callback(conditionBuilder, rightProxy, leftProxy);
93
98
  const lateralSQL = buildLateralSubquery(rightTableName, rightAlias, conditionBuilder, rightTableDef);
94
99
  const lateralJoinType = joinType === 'LEFT JOIN' ? 'LEFT JOIN LATERAL' : 'JOIN LATERAL';
95
100
  const joinClause = {
@@ -109,12 +114,21 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
109
114
  const internals = builder[JOIN_INTERNAL];
110
115
  parts.push('SELECT');
111
116
  const selectedProps = internals.getSelectedColumns();
117
+ const innerJoins = internals.getInnerJoins();
118
+ const hasInnerJoins = innerJoins.length > 0;
119
+ const toSnake = (s) => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`);
112
120
  if (selectedProps && selectedProps.length > 0) {
113
121
  const tableColumns = tableDef?.$columns || tableDef;
114
122
  const selectCols = selectedProps.map(prop => {
115
123
  const columnDef = tableColumns?.[prop];
116
- const sqlName = columnDef?.$columnName || prop;
117
- return `"${alias}"."${sqlName}" AS "${prop}"`;
124
+ if (columnDef || !hasInnerJoins) {
125
+ const sqlName = columnDef?.$columnName || toSnake(prop);
126
+ return `"${alias}"."${sqlName}" AS "${prop}"`;
127
+ }
128
+ else {
129
+ const sqlName = toSnake(prop);
130
+ return `"${sqlName}" AS "${prop}"`;
131
+ }
118
132
  }).join(', ');
119
133
  parts.push(selectCols);
120
134
  }
@@ -122,7 +136,6 @@ function buildLateralSubquery(tableName, alias, builder, tableDef) {
122
136
  parts.push(`"${alias}".*`);
123
137
  }
124
138
  parts.push(`FROM "${tableName}" AS "${alias}"`);
125
- const innerJoins = internals.getInnerJoins();
126
139
  for (const join of innerJoins) {
127
140
  parts.push(`${join.type} "${join.table}" AS "${join.alias}" ON ${join.onClause}`);
128
141
  }
@@ -91,12 +91,12 @@ export class JoinConditionBuilder {
91
91
  this.whereConditions.push(...collector.getConditions());
92
92
  return this;
93
93
  }
94
- select(columns) {
95
- if (columns === '*') {
96
- this.selectedColumns = undefined;
94
+ select(...args) {
95
+ if (args.length === 1 && Array.isArray(args[0])) {
96
+ this.selectedColumns = args[0];
97
97
  }
98
98
  else {
99
- this.selectedColumns = columns;
99
+ this.selectedColumns = args;
100
100
  }
101
101
  return this;
102
102
  }
@@ -27,28 +27,34 @@ export class JoinManyConditionBuilder extends JoinConditionBuilder {
27
27
  this.rightProxy = rightProxy;
28
28
  };
29
29
  }
30
- innerJoin(table, callback) {
30
+ innerJoin(tableOrAlias, callback) {
31
31
  if (!this.proxyCreator) {
32
32
  throw new Error('innerJoin requires proxy creator - use raw innerJoinRaw() instead');
33
33
  }
34
- const { proxy: innerProxy, tableName } = this.proxyCreator(table, table);
34
+ const [tableKey, alias] = Array.isArray(tableOrAlias)
35
+ ? tableOrAlias
36
+ : [tableOrAlias, tableOrAlias];
37
+ const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
35
38
  const conditionBuilder = new JoinConditionBuilder();
36
39
  callback(conditionBuilder, innerProxy);
37
40
  const internals = conditionBuilder[JOIN_INTERNAL];
38
41
  const onClause = internals.toSQL();
39
- this.innerJoins.push({ type: 'JOIN', table: tableName, alias: table, onClause });
42
+ this.innerJoins.push({ type: 'JOIN', table: tableName, alias, onClause });
40
43
  return this;
41
44
  }
42
- leftInnerJoin(table, callback) {
45
+ leftInnerJoin(tableOrAlias, callback) {
43
46
  if (!this.proxyCreator) {
44
47
  throw new Error('leftInnerJoin requires proxy creator - use raw leftInnerJoinRaw() instead');
45
48
  }
46
- const { proxy: innerProxy, tableName } = this.proxyCreator(table, table);
49
+ const [tableKey, alias] = Array.isArray(tableOrAlias)
50
+ ? tableOrAlias
51
+ : [tableOrAlias, tableOrAlias];
52
+ const { proxy: innerProxy, tableName } = this.proxyCreator(tableKey, alias);
47
53
  const conditionBuilder = new JoinConditionBuilder();
48
54
  callback(conditionBuilder, innerProxy);
49
55
  const internals = conditionBuilder[JOIN_INTERNAL];
50
56
  const onClause = internals.toSQL();
51
- this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias: table, onClause });
57
+ this.innerJoins.push({ type: 'LEFT JOIN', table: tableName, alias, onClause });
52
58
  return this;
53
59
  }
54
60
  innerJoinRaw(table, alias, onClause) {
@@ -59,12 +65,12 @@ export class JoinManyConditionBuilder extends JoinConditionBuilder {
59
65
  this.innerJoins.push({ type: 'LEFT JOIN', table, alias, onClause });
60
66
  return this;
61
67
  }
62
- select(columns) {
63
- if (columns === '*') {
64
- this.selectedColumns = undefined;
68
+ select(...args) {
69
+ if (args.length === 1 && Array.isArray(args[0])) {
70
+ this.selectedColumns = args[0];
65
71
  }
66
72
  else {
67
- this.selectedColumns = columns;
73
+ this.selectedColumns = args;
68
74
  }
69
75
  return this;
70
76
  }
package/dist/index.d.ts CHANGED
@@ -7644,17 +7644,17 @@ declare class JoinConditionBuilder<TLeft = any, TRight = any> {
7644
7644
  where(callback: (q: TypedConditionBuilder<TRight>) => TypedConditionBuilder<TRight>): this;
7645
7645
  /**
7646
7646
  * Select specific columns from the joined table.
7647
- * If not called or called with '*', all columns are selected.
7647
+ * If not called, all columns are selected.
7648
7648
  * The return type narrows TRight to only the selected columns.
7649
7649
  *
7650
- * @param columns - Array of column names to select, or '*' for all columns
7651
- *
7652
7650
  * @example
7653
7651
  * on.equal(orders.userId, users.id)
7654
- * .select(['id', 'name', 'email'])
7655
- * on.select('*') // Select all (default)
7652
+ * .select(['id', 'name', 'email']) // array syntax
7653
+ * on.equal(orders.userId, users.id)
7654
+ * .select('id', 'name', 'email') // spread syntax
7656
7655
  */
7657
- select<K extends ColumnKeys<TRight>>(columns: K[] | "*"): JoinConditionBuilder<TLeft, PickColumns<TRight, K>>;
7656
+ select<K extends ColumnKeys<TRight>>(columns: K[]): JoinConditionBuilder<TLeft, PickColumns<TRight, K>>;
7657
+ select<K extends ColumnKeys<TRight>>(...columns: K[]): JoinConditionBuilder<TLeft, PickColumns<TRight, K>>;
7658
7658
  /** @internal */
7659
7659
  get [JOIN_INTERNAL](): JoinConditionInternals;
7660
7660
  /**
@@ -7786,7 +7786,10 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
7786
7786
  * // JOIN LATERAL (SELECT ... FROM purchases JOIN products ON ... WHERE ...) ...
7787
7787
  * ```
7788
7788
  */
7789
- innerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(table: TInnerKey, callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
7789
+ innerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(tableOrAlias: TInnerKey | [
7790
+ TInnerKey,
7791
+ string
7792
+ ], callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
7790
7793
  /**
7791
7794
  * Add a LEFT JOIN within the LATERAL subquery.
7792
7795
  * Autocomplete excludes parent tables already in scope.
@@ -7794,7 +7797,10 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
7794
7797
  * @param table - Table name (schema key) to join
7795
7798
  * @param callback - Join callback receiving (on, innerTable)
7796
7799
  */
7797
- leftInnerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(table: TInnerKey, callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
7800
+ leftInnerJoin<TInnerKey extends Exclude<keyof TSchema & string, TRightKey>>(tableOrAlias: TInnerKey | [
7801
+ TInnerKey,
7802
+ string
7803
+ ], callback: InnerJoinCallback<TRight, TSchema[TInnerKey]>): this;
7798
7804
  /**
7799
7805
  * Add a raw inner JOIN with SQL string (no type safety).
7800
7806
  * Use when you don't have schema access.
@@ -7812,9 +7818,12 @@ declare class JoinManyConditionBuilder<TSchema = any, TLeft = any, TRight = any,
7812
7818
  * Select specific columns from the joined table.
7813
7819
  * The return type narrows TRight to only the selected columns.
7814
7820
  *
7815
- * @param columns - Array of column names to select, or '*' for all columns
7821
+ * @example
7822
+ * on.select(['id', 'name']) // array syntax
7823
+ * on.select('id', 'name') // spread syntax
7816
7824
  */
7817
- select<K extends ColumnKeys<TRight>>(columns: K[] | "*"): JoinManyConditionBuilder<TSchema, TLeft, PickColumns<TRight, K>, TRightKey>;
7825
+ select<K extends ColumnKeys<TRight>>(columns: K[]): JoinManyConditionBuilder<TSchema, TLeft, PickColumns<TRight, K>, TRightKey>;
7826
+ select<K extends ColumnKeys<TRight>>(...columns: K[]): JoinManyConditionBuilder<TSchema, TLeft, PickColumns<TRight, K>, TRightKey>;
7818
7827
  /** @internal */
7819
7828
  get [JOIN_INTERNAL](): JoinManyInternals;
7820
7829
  /**
@@ -8502,45 +8511,63 @@ export type InferResultType<TSchema, TTable, TColumns> = TColumns extends [
8502
8511
  } ? TColumns extends readonly string[] ? Simplify$1<Pick<TSelect, Extract<TColumns[number], keyof TSelect>>> : TSelect : SelectResult<TTable, TColumns extends readonly any[] ? TColumns : [
8503
8512
  ]>;
8504
8513
  /**
8505
- * Join callback function type with positional parameters for better type inference.
8506
- * TResult allows the callback to return a narrowed type (e.g., after .select())
8514
+ * Join callback function type for join/innerJoin/leftJoin.
8515
+ * The joined table proxy comes FIRST for natural DX:
8516
+ * when you write `.join('orders', ...)`, `orders` is what you think about first.
8517
+ *
8518
+ * @param on - The condition builder for ON clause
8519
+ * @param joined - Table proxy for the joined table (the one in .join('tableName'))
8520
+ * @param source - Table proxy for the source table (the one .join() is called on)
8521
+ *
8522
+ * @example
8523
+ * ```typescript
8524
+ * db.table.users.select()
8525
+ * .join('orders', (on, orders, users) =>
8526
+ * on.equal(orders.userId, users.id)
8527
+ * .select(['id', 'total'])
8528
+ * )
8529
+ * ```
8530
+ */
8531
+ export type JoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, joined: TableProxy<TRight>, source: TableProxy<TLeft>) => JoinConditionBuilder<TLeft, TResult>;
8532
+ /**
8533
+ * Right join callback — reversed parameter order from JoinCallback.
8534
+ * For rightJoin, the source table comes first since the right (joined) table
8535
+ * is the primary table in a RIGHT JOIN.
8507
8536
  *
8508
8537
  * @param on - The condition builder for ON clause
8509
- * @param left - Table proxy for the left (current) table
8510
- * @param right - Table proxy for the right (joined) table
8538
+ * @param source - Table proxy for the source table
8539
+ * @param joined - Table proxy for the joined (right/primary) table
8511
8540
  *
8512
8541
  * @example
8513
8542
  * ```typescript
8514
- * // Positional params provide better autocomplete and type inference
8515
- * .join('users', (on, orders, users) =>
8516
- * on.equal(orders.userId, users.id)
8517
- * .select(['id', 'name']) // Narrows result to only these columns
8518
- * )
8543
+ * db.table.users.select()
8544
+ * .rightJoin('orders', (on, users, orders) =>
8545
+ * on.equal(users.id, orders.userId)
8546
+ * )
8519
8547
  * ```
8520
8548
  */
8521
- export type JoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, left: TableProxy<TLeft>, right: TableProxy<TRight>) => JoinConditionBuilder<TLeft, TResult>;
8549
+ export type RightJoinCallback<TLeft, TRight, TResult = TRight> = (on: JoinConditionBuilder<TLeft, TRight>, source: TableProxy<TLeft>, joined: TableProxy<TRight>) => JoinConditionBuilder<TLeft, TResult>;
8522
8550
  /**
8523
8551
  * JoinMany callback function type for LATERAL subqueries.
8524
- * Provides additional orderBy, limit, offset capabilities.
8525
- * Includes schema for type-safe inner joins with autocomplete.
8526
- * TResult allows the callback to return a narrowed type (e.g., after .select())
8552
+ * Same parameter order as JoinCallback: joined table first, source second.
8527
8553
  *
8528
8554
  * @param on - The condition builder for LATERAL subquery
8529
- * @param left - Table proxy for the left (current/outer) table
8530
- * @param right - Table proxy for the right (joined/inner) table
8555
+ * @param joined - Table proxy for the joined table
8556
+ * @param source - Table proxy for the source (outer) table
8531
8557
  *
8532
8558
  * @example
8533
8559
  * ```typescript
8534
8560
  * // Get top 5 orders per user
8535
- * .joinMany('orders', (on, users, orders) =>
8536
- * on.equal(users.id, orders.userId)
8537
- * .where(q => q.equal('status', 'completed'))
8538
- * .orderBy(orders.createdAt, 'DESC')
8539
- * .limit(5)
8540
- * )
8561
+ * db.table.users.select()
8562
+ * .joinMany('orders', (on, orders, users) =>
8563
+ * on.equal(orders.userId, users.id)
8564
+ * .where(q => q.equal('status', 'completed'))
8565
+ * .orderBy(orders.createdAt, 'DESC')
8566
+ * .limit(5)
8567
+ * )
8541
8568
  * ```
8542
8569
  */
8543
- export type JoinManyCallback<TSchema, TLeft, TRight, TRightKey extends string, TResult = TRight> = (on: JoinManyConditionBuilder<TSchema, TLeft, TRight, TRightKey>, left: TableProxy<TLeft>, right: TableProxy<TRight>) => JoinManyConditionBuilder<TSchema, TLeft, TResult, TRightKey>;
8570
+ export type JoinManyCallback<TSchema, TLeft, TRight, TRightKey extends string, TResult = TRight> = (on: JoinManyConditionBuilder<TSchema, TLeft, TRight, TRightKey>, joined: TableProxy<TRight>, source: TableProxy<TLeft>) => JoinManyConditionBuilder<TSchema, TLeft, TResult, TRightKey>;
8544
8571
  /**
8545
8572
  * Internal interface for query builders
8546
8573
  * This interface exposes execution methods that are hidden from the public API
@@ -8794,16 +8821,16 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8794
8821
  * .join('users') // Auto-detects orders.userId → users.id
8795
8822
  * // Result: { ...order, users: { id, name, ... } }
8796
8823
  *
8797
- * // With explicit callback
8824
+ * // With explicit callback — joined table first, source second
8798
8825
  * db.table.orders.select()
8799
- * .join('users', (on, orders, users) =>
8800
- * on.equal(orders.userId, users.id)
8826
+ * .join('users', (on, users, orders) =>
8827
+ * on.equal(users.id, orders.userId)
8801
8828
  * )
8802
8829
  *
8803
8830
  * // With alias
8804
8831
  * db.table.orders.select()
8805
- * .join(['users', 'user'], (on, orders, user) =>
8806
- * on.equal(orders.userId, user.id)
8832
+ * .join(['users', 'user'], (on, user, orders) =>
8833
+ * on.equal(user.id, orders.userId)
8807
8834
  * )
8808
8835
  * // Result: { ...order, user: { id, name, ... } }
8809
8836
  * ```
@@ -8829,10 +8856,10 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8829
8856
  * .leftJoin('users')
8830
8857
  * // Result: { ...order, users: { ... } | null }
8831
8858
  *
8832
- * // With callback
8859
+ * // With callback — joined table first, source second
8833
8860
  * db.table.orders.select()
8834
- * .leftJoin(['users', 'user'], (on, orders, user) =>
8835
- * on.equal(orders.userId, user.id)
8861
+ * .leftJoin(['users', 'user'], (on, user, orders) =>
8862
+ * on.equal(user.id, orders.userId)
8836
8863
  * )
8837
8864
  * ```
8838
8865
  */
@@ -8848,12 +8875,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8848
8875
  leftJoin<TRightKey extends keyof TSchema & string, TResult>(table: TRightKey, callback: JoinCallback<TTable, TSchema[TRightKey], TResult>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedLeftJoin<TRightKey, TResult>>;
8849
8876
  /**
8850
8877
  * Type-safe RIGHT JOIN.
8878
+ * Callback order is (on, source, joined) — reversed from join/leftJoin
8879
+ * because in a RIGHT JOIN the joined table is the primary table.
8851
8880
  *
8852
8881
  * @example
8853
8882
  * ```typescript
8854
8883
  * db.table.orders.select()
8855
- * .rightJoin('users')
8856
- * // Result: { ...order, users: { ... } }
8884
+ * .rightJoin('users', (on, orders, users) =>
8885
+ * on.equal(orders.userId, users.id)
8886
+ * )
8857
8887
  * ```
8858
8888
  */
8859
8889
  rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
@@ -8864,8 +8894,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8864
8894
  rightJoin<TRightKey extends keyof TSchema & string, TAlias extends string>(tableAndAlias: [
8865
8895
  TRightKey,
8866
8896
  TAlias
8867
- ], callback: JoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TAlias, TSchema[TRightKey]>>;
8868
- rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback: JoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TRightKey, TSchema[TRightKey]>>;
8897
+ ], callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TAlias, TSchema[TRightKey]>>;
8898
+ rightJoin<TRightKey extends keyof TSchema & string>(table: TRightKey, callback: RightJoinCallback<TTable, TSchema[TRightKey]>): ConnectedSelectBuilder<TSchema, TTable, TColumns, TJoined & NestedJoin<TRightKey, TSchema[TRightKey]>>;
8869
8899
  /**
8870
8900
  * Type-safe INNER JOIN (alias for join()).
8871
8901
  */
@@ -8893,8 +8923,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8893
8923
  * db.table.users.select()
8894
8924
  * .joinSubquery(
8895
8925
  * 'recent_orders',
8896
- * db.table.orders.select().join('payments', (on, o, p) =>
8897
- * on.equal(o.id, p.orderId)
8926
+ * db.table.orders.select().join('payments', (on, p, o) =>
8927
+ * on.equal(p.orderId, o.id)
8898
8928
  * ),
8899
8929
  * `"recent_orders"."user_id" = "users"."id"`
8900
8930
  * )
@@ -8944,15 +8974,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8944
8974
  * | SQLite | ❌ | Use separate queries |
8945
8975
  *
8946
8976
  * @param tableOrAlias - Table name or [tableName, alias] tuple
8947
- * @param callback - Join condition callback: `(on, left, right) => on.equal(...)`
8977
+ * @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
8948
8978
  * @throws {RelqConfigError} If dialect doesn't support LATERAL joins
8949
8979
  *
8950
8980
  * @example
8951
8981
  * ```typescript
8952
- * // Get top 5 orders per user
8982
+ * // Get top 5 orders per user — joined table first, source second
8953
8983
  * db.table.users.select()
8954
- * .joinMany('orders', (on, users, orders) =>
8955
- * on.equal(users.id, orders.userId)
8984
+ * .joinMany('orders', (on, orders, users) =>
8985
+ * on.equal(orders.userId, users.id)
8956
8986
  * .where(q => q.equal('status', 'completed'))
8957
8987
  * .orderBy('createdAt', 'DESC')
8958
8988
  * .limit(5)
@@ -8962,8 +8992,8 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8962
8992
  *
8963
8993
  * // With alias
8964
8994
  * db.table.users.select()
8965
- * .joinMany(['orders', 'recentOrders'], (on, users, orders) =>
8966
- * on.equal(users.id, orders.userId)
8995
+ * .joinMany(['orders', 'recentOrders'], (on, orders, users) =>
8996
+ * on.equal(orders.userId, users.id)
8967
8997
  * .orderBy('createdAt', 'DESC')
8968
8998
  * .limit(3)
8969
8999
  * )
@@ -8990,15 +9020,15 @@ declare class ConnectedSelectBuilder<TSchema = any, TTable = any, TColumns exten
8990
9020
  * | SQLite | ❌ | Use separate queries |
8991
9021
  *
8992
9022
  * @param tableOrAlias - Table name or [tableName, alias] tuple
8993
- * @param callback - Join condition callback: `(on, left, right) => on.equal(...)`
9023
+ * @param callback - Join condition callback: `(on, joined, source) => on.equal(...)`
8994
9024
  * @throws {RelqConfigError} If dialect doesn't support LATERAL joins
8995
9025
  *
8996
9026
  * @example
8997
9027
  * ```typescript
8998
9028
  * // Get all users with their orders (empty array if no orders)
8999
9029
  * db.table.users.select()
9000
- * .leftJoinMany('orders', (on, users, orders) =>
9001
- * on.equal(users.id, orders.userId)
9030
+ * .leftJoinMany('orders', (on, orders, users) =>
9031
+ * on.equal(orders.userId, users.id)
9002
9032
  * .where(q => q.equal('status', 'completed'))
9003
9033
  * )
9004
9034
  * .all()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relq",
3
- "version": "1.0.86",
3
+ "version": "1.0.88",
4
4
  "description": "The Fully-Typed PostgreSQL ORM for TypeScript",
5
5
  "author": "Olajide Mathew O. <olajide.mathew@yuniq.solutions>",
6
6
  "license": "MIT",