orchid-orm 1.17.38 → 1.18.1

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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Query, QueryWithTable, SetQueryTableAlias, WhereArg, UpdateData, CreateData, AddQueryDefaults, Db, IsolationLevel, TransactionOptions, Adapter, FromArgs, FromResult, AdapterOptions, QueryLogOptions, NoPrimaryKeyOption, RelationQuery, RelationConfigBase, RelationQueryBase, ComputedColumnsBase, QueryData, QueryBase, DefaultColumnTypes, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery, SetQueryReturns, QueryReturnType } from 'pqb';
1
+ import { Query, QueryWithTable, SetQueryTableAlias, RelationJoinQuery, WhereArg, UpdateData, CreateData, AddQueryDefaults, Db, IsolationLevel, TransactionOptions, Adapter, FromArgs, FromResult, AdapterOptions, QueryLogOptions, NoPrimaryKeyOption, RelationQuery, RelationConfigBase, RelationQueryBase, ComputedColumnsBase, QueryData, QueryBase, DbTableOptionScopes, DefaultColumnTypes, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery, SetQueryReturns, QueryReturnType } from 'pqb';
2
2
  export * from 'pqb';
3
- import { EmptyObject, MaybeArray, StringKey, ColumnsShapeBase, ColumnShapeQueryType, ColumnShapeOutput, ColumnShapeInput } from 'orchid-core';
3
+ import { ColumnsShapeBase, EmptyObject, MaybeArray, StringKey, CoreQueryScopes, ColumnShapeQueryType, ColumnShapeOutput, ColumnShapeInput } from 'orchid-core';
4
4
 
5
5
  type RelationCommonOptions<Related extends TableClass = TableClass, Scope extends Query = Query> = {
6
6
  scope?: ScopeFn<Related, Scope>;
@@ -25,14 +25,14 @@ type BelongsTo = RelationThunkBase & {
25
25
  type: 'belongsTo';
26
26
  options: BelongsToOptions;
27
27
  };
28
- type BelongsToOptions<Self extends Table = Table, Related extends TableClass = TableClass, Scope extends Query = Query> = RelationCommonOptions<Related, Scope> & RelationRefsOrKeysOptions<keyof Self['columns'], keyof InstanceType<Related>['columns'], keyof InstanceType<Related>['columns'], keyof Self['columns']>;
28
+ type BelongsToOptions<Columns extends ColumnsShapeBase = ColumnsShapeBase, Related extends TableClass = TableClass, Scope extends Query = Query> = RelationCommonOptions<Related, Scope> & RelationRefsOrKeysOptions<keyof Columns, keyof InstanceType<Related>['columns'], keyof InstanceType<Related>['columns'], keyof Columns>;
29
29
  type BelongsToInfo<T extends Table, Relation extends BelongsTo, K extends string, FK extends string = Relation['options'] extends RelationRefsOptions ? Relation['options']['columns'][number] : Relation['options'] extends RelationKeysOptions ? Relation['options']['foreignKey'] : never, Q extends QueryWithTable = SetQueryTableAlias<DbTable<ReturnType<Relation['fn']>>, K>, DataForCreate = RelationToOneDataForCreate<{
30
30
  nestedCreateQuery: Q;
31
31
  table: Q;
32
32
  }>, Required = Relation['options']['required'] extends true ? true : false> = {
33
33
  table: Q;
34
34
  query: Q;
35
- joinQuery(fromQuery: Query, toQuery: Query): Query;
35
+ joinQuery: RelationJoinQuery;
36
36
  one: true;
37
37
  required: Required;
38
38
  omitForeignKeyInCreate: FK;
@@ -76,11 +76,11 @@ type HasMany = RelationThunkBase & {
76
76
  type: 'hasMany';
77
77
  options: HasManyOptions;
78
78
  };
79
- type HasManyOptions<Self extends Table = Table, Related extends TableClass = TableClass, Scope extends Query = Query, Through extends string = string, Source extends string = string> = HasOneOptions<Self, Related, Scope, Through, Source>;
79
+ type HasManyOptions<Columns extends ColumnsShapeBase = ColumnsShapeBase, Related extends TableClass = TableClass, Scope extends Query = Query, Through extends string = string, Source extends string = string> = HasOneOptions<Columns, Related, Scope, Through, Source>;
80
80
  type HasManyInfo<T extends Table, Relations extends RelationThunks, Relation extends HasMany, K extends string, Populate extends Record<string, true> = Relation['options'] extends RelationRefsOptions ? Record<Relation['options']['references'][number], true> : Relation['options'] extends RelationKeysOptions ? Record<Relation['options']['foreignKey'], true> : never, TC extends TableClass = ReturnType<Relation['fn']>, Q extends QueryWithTable = SetQueryTableAlias<DbTable<TC>, K>, NestedCreateQuery extends Query = Relation['options'] extends RelationThroughOptions ? Q : AddQueryDefaults<Q, Populate>> = {
81
81
  table: Q;
82
82
  query: Q;
83
- joinQuery(fromQuery: Query, toQuery: Query): Query;
83
+ joinQuery: RelationJoinQuery;
84
84
  one: false;
85
85
  required: Relation['options']['required'] extends true ? true : false;
86
86
  omitForeignKeyInCreate: never;
@@ -114,11 +114,11 @@ type HasOne = RelationThunkBase & {
114
114
  type: 'hasOne';
115
115
  options: HasOneOptions;
116
116
  };
117
- type HasOneOptions<Self extends Table = Table, Related extends TableClass = TableClass, Scope extends Query = Query, Through extends string = string, Source extends string = string> = RelationCommonOptions<Related, Scope> & (RelationHasOptions<keyof Self['columns'], keyof InstanceType<Related>['columns']> | RelationThroughOptions<Through, Source>);
117
+ type HasOneOptions<Columns extends ColumnsShapeBase = ColumnsShapeBase, Related extends TableClass = TableClass, Scope extends Query = Query, Through extends string = string, Source extends string = string> = RelationCommonOptions<Related, Scope> & (RelationHasOptions<keyof Columns, keyof InstanceType<Related>['columns']> | RelationThroughOptions<Through, Source>);
118
118
  type HasOneInfo<T extends Table, Relations extends RelationThunks, Relation extends HasOne, K extends string, Populate extends Record<string, true> = Relation['options'] extends RelationRefsOptions ? Record<Relation['options']['references'][number], true> : Relation['options'] extends RelationKeysOptions ? Record<Relation['options']['foreignKey'], true> : never, TC extends TableClass = ReturnType<Relation['fn']>, Q extends QueryWithTable = SetQueryTableAlias<DbTable<TC>, K>, NestedCreateQuery extends Query = Relation['options'] extends RelationThroughOptions ? Q : AddQueryDefaults<Q, Populate>> = {
119
119
  table: Q;
120
120
  query: Q;
121
- joinQuery(fromQuery: Query, toQuery: Query): Query;
121
+ joinQuery: RelationJoinQuery;
122
122
  one: true;
123
123
  required: Relation['options']['required'] extends true ? true : false;
124
124
  omitForeignKeyInCreate: never;
@@ -239,8 +239,8 @@ type HasAndBelongsToMany = RelationThunkBase & {
239
239
  type: 'hasAndBelongsToMany';
240
240
  options: HasAndBelongsToManyOptions;
241
241
  };
242
- type HasAndBelongsToManyOptions<Self extends Table = Table, Related extends TableClass = TableClass, Scope extends Query = Query> = RelationCommonOptions<Related, Scope> & ({
243
- columns: (keyof Self['columns'])[];
242
+ type HasAndBelongsToManyOptions<Columns extends ColumnsShapeBase = ColumnsShapeBase, Related extends TableClass = TableClass, Scope extends Query = Query> = RelationCommonOptions<Related, Scope> & ({
243
+ columns: (keyof Columns)[];
244
244
  references: string[];
245
245
  through: {
246
246
  table: string;
@@ -248,7 +248,7 @@ type HasAndBelongsToManyOptions<Self extends Table = Table, Related extends Tabl
248
248
  references: (keyof InstanceType<Related>['columns'])[];
249
249
  };
250
250
  } | {
251
- primaryKey: keyof Self['columns'];
251
+ primaryKey: keyof Columns;
252
252
  foreignKey: string;
253
253
  joinTable: string;
254
254
  associationPrimaryKey: string;
@@ -257,7 +257,7 @@ type HasAndBelongsToManyOptions<Self extends Table = Table, Related extends Tabl
257
257
  type HasAndBelongsToManyInfo<T extends Table, Relation extends HasAndBelongsToMany, K extends string, TC extends TableClass = ReturnType<Relation['fn']>, Q extends QueryWithTable = SetQueryTableAlias<DbTable<TC>, K>> = {
258
258
  table: Q;
259
259
  query: Q;
260
- joinQuery(fromQuery: Query, toQuery: Query): Query;
260
+ joinQuery: RelationJoinQuery;
261
261
  one: false;
262
262
  required: Relation['options']['required'] extends true ? true : false;
263
263
  omitForeignKeyInCreate: never;
@@ -344,7 +344,7 @@ type TableClass<T extends Table = Table> = {
344
344
  type TableClasses = Record<string, TableClass>;
345
345
  type TableToDb<T extends Table, RelationQueries extends Record<string, RelationQueryBase>> = Db<T['table'], T['columns'], RelationQueries, T['types'], T['computed'] extends ComputedColumnsBase<never> ? T['columns'] & {
346
346
  [K in keyof T['computed']]: ReturnType<T['computed'][K]>['_type'];
347
- } : T['columns']> & {
347
+ } : T['columns'], T['scopes']> & {
348
348
  definedAs: string;
349
349
  db: OrchidORM;
350
350
  getFilePath(): string;
@@ -364,6 +364,7 @@ type Table = {
364
364
  * collect computed columns returned by {@link BaseTable.setColumns}
365
365
  */
366
366
  computed?: ComputedColumnsBase<never>;
367
+ scopes?: CoreQueryScopes;
367
368
  };
368
369
  type Queryable<T extends Table> = Partial<ColumnShapeQueryType<T['columns']>>;
369
370
  type Selectable<T extends Table> = ColumnShapeOutput<T['columns']>;
@@ -478,22 +479,37 @@ interface BaseTableInstance<ColumnTypes> {
478
479
  * @param computed - object where keys are column names and values are functions returning raw SQL
479
480
  */
480
481
  setComputed<Table extends string, Shape extends ColumnsShapeBase, Computed extends ComputedColumnsBase<Db<Table, Shape, EmptyObject, ColumnTypes>>>(computed: Computed): Computed;
481
- belongsTo<Self extends Table, Related extends TableClass, Scope extends Query, Options extends BelongsToOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
482
+ /**
483
+ * See {@link ScopeMethods}
484
+ */
485
+ setScopes<Table extends string, Columns extends ColumnsShapeBase, Keys extends string>(this: {
486
+ table: Table;
487
+ columns: Columns;
488
+ }, scopes: DbTableOptionScopes<Table, Columns, Keys>): CoreQueryScopes<Keys>;
489
+ belongsTo<Columns extends ColumnsShapeBase, Related extends TableClass, Scope extends Query, Options extends BelongsToOptions<Columns, Related, Scope>>(this: {
490
+ columns: Columns;
491
+ }, fn: () => Related, options: Options): {
482
492
  type: 'belongsTo';
483
493
  fn: () => Related;
484
494
  options: Options;
485
495
  };
486
- hasOne<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasOneOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
496
+ hasOne<Columns extends ColumnsShapeBase, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasOneOptions<Columns, Related, Scope, Through, Source>>(this: {
497
+ columns: Columns;
498
+ }, fn: () => Related, options: Options): {
487
499
  type: 'hasOne';
488
500
  fn: () => Related;
489
501
  options: Options;
490
502
  };
491
- hasMany<Self extends Table, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasManyOptions<Self, Related, Scope, Through, Source>>(this: Self, fn: () => Related, options: Options): {
503
+ hasMany<Columns extends ColumnsShapeBase, Related extends TableClass, Scope extends Query, Through extends string, Source extends string, Options extends HasManyOptions<Columns, Related, Scope, Through, Source>>(this: {
504
+ columns: Columns;
505
+ }, fn: () => Related, options: Options): {
492
506
  type: 'hasMany';
493
507
  fn: () => Related;
494
508
  options: Options;
495
509
  };
496
- hasAndBelongsToMany<Self extends Table, Related extends TableClass, Scope extends Query, Options extends HasAndBelongsToManyOptions<Self, Related, Scope>>(this: Self, fn: () => Related, options: Options): {
510
+ hasAndBelongsToMany<Columns extends ColumnsShapeBase, Related extends TableClass, Scope extends Query, Options extends HasAndBelongsToManyOptions<Columns, Related, Scope>>(this: {
511
+ columns: Columns;
512
+ }, fn: () => Related, options: Options): {
497
513
  type: 'hasAndBelongsToMany';
498
514
  fn: () => Related;
499
515
  options: Options;
package/dist/index.js CHANGED
@@ -82,6 +82,9 @@ function createBaseTable({
82
82
  setComputed(computed) {
83
83
  return computed;
84
84
  }
85
+ setScopes(scopes) {
86
+ return scopes;
87
+ }
85
88
  belongsTo(fn, options) {
86
89
  return {
87
90
  type: "belongsTo",
@@ -182,31 +185,45 @@ const relationWhere = (len, keys, valueKeys) => (params) => {
182
185
  }
183
186
  return obj;
184
187
  };
185
- function joinHasThrough(q, fromQuery, toQuery, throughRelation, sourceRelation) {
188
+ function joinHasThrough(q, baseQuery, joiningQuery, throughRelation, sourceRelation) {
186
189
  return q.whereExists(
187
- throughRelation.joinQuery(fromQuery, throughRelation.query),
190
+ throughRelation.joinQuery(throughRelation.query, baseQuery),
188
191
  () => {
189
- const as = pqb.getQueryAs(toQuery);
192
+ const as = pqb.getQueryAs(joiningQuery);
190
193
  return sourceRelation.joinQuery(
191
- throughRelation.query,
192
- sourceRelation.query.as(as)
194
+ sourceRelation.query.as(as),
195
+ throughRelation.query
193
196
  );
194
197
  }
195
198
  );
196
199
  }
197
- function joinHasRelation(fromQuery, toQuery, primaryKeys, foreignKeys, len) {
198
- const q = toQuery.clone();
200
+ function joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len) {
201
+ const q = joiningQuery.clone();
199
202
  pqb.setQueryObjectValue(
200
203
  q,
201
204
  "joinedShapes",
202
- fromQuery.q.as || fromQuery.table,
203
- fromQuery.q.shape
205
+ baseQuery.q.as || baseQuery.table,
206
+ baseQuery.q.shape
204
207
  );
205
208
  for (let i = 0; i < len; i++) {
206
- pqb.pushQueryOn(q, fromQuery, toQuery, foreignKeys[i], primaryKeys[i]);
209
+ pqb.pushQueryOn(q, baseQuery, joiningQuery, foreignKeys[i], primaryKeys[i]);
207
210
  }
208
211
  return q;
209
212
  }
213
+ const joinQueryChainingHOF = (reverseJoin, joinQuery) => (joiningQuery, baseQuery) => {
214
+ const chain = joiningQuery.q.relChain;
215
+ if (!chain || chain.length === 1) {
216
+ return joinQuery(joiningQuery, baseQuery);
217
+ }
218
+ const last = chain[chain.length - 1];
219
+ const query = "relationConfig" in last ? last.relationConfig.joinQuery(last, baseQuery) : last;
220
+ const inner = reverseJoin(query, joiningQuery);
221
+ return joiningQuery.where({
222
+ EXISTS: {
223
+ args: [inner]
224
+ }
225
+ });
226
+ };
210
227
 
211
228
  class BelongsToVirtualColumn extends pqb.VirtualColumn {
212
229
  constructor(key, state) {
@@ -266,31 +283,33 @@ const makeBelongsToMethod = (relation, relationName, query) => {
266
283
  const len = primaryKeys.length;
267
284
  const state = { query, primaryKeys, foreignKeys, len };
268
285
  const makeWhere = relationWhere(len, primaryKeys, foreignKeys);
269
- const join = (fromQuery, toQuery, primaryKeys2, foreignKeys2) => {
270
- const q = toQuery.clone();
286
+ const join = (baseQuery, joiningQuery, primaryKeys2, foreignKeys2) => {
287
+ const q = joiningQuery.clone();
271
288
  pqb.setQueryObjectValue(
272
289
  q,
273
290
  "joinedShapes",
274
- fromQuery.q.as || fromQuery.table,
275
- fromQuery.q.shape
291
+ baseQuery.q.as || baseQuery.table,
292
+ baseQuery.q.shape
276
293
  );
277
294
  for (let i = 0; i < len; i++) {
278
- pqb.pushQueryOn(q, fromQuery, toQuery, primaryKeys2[i], foreignKeys2[i]);
295
+ pqb.pushQueryOn(q, baseQuery, joiningQuery, primaryKeys2[i], foreignKeys2[i]);
279
296
  }
280
297
  return q;
281
298
  };
299
+ const reverseJoin = (baseQuery, joiningQuery) => {
300
+ return join(joiningQuery, baseQuery, foreignKeys, primaryKeys);
301
+ };
282
302
  return {
283
303
  returns: "one",
284
304
  method(params) {
285
305
  return query.where(makeWhere(params));
286
306
  },
287
307
  virtualColumn: new BelongsToVirtualColumn(relationName, state),
288
- joinQuery(fromQuery, toQuery) {
289
- return join(fromQuery, toQuery, primaryKeys, foreignKeys);
290
- },
291
- reverseJoin(fromQuery, toQuery) {
292
- return join(toQuery, fromQuery, foreignKeys, primaryKeys);
293
- }
308
+ joinQuery: joinQueryChainingHOF(
309
+ reverseJoin,
310
+ (joiningQuery, baseQuery) => join(baseQuery, joiningQuery, primaryKeys, foreignKeys)
311
+ ),
312
+ reverseJoin
294
313
  };
295
314
  };
296
315
  const nestedInsert$3 = ({ query, primaryKeys }) => {
@@ -524,8 +543,17 @@ const makeHasOneMethod = (table, relation, relationName, query) => {
524
543
  const { through, source } = relation.options;
525
544
  const throughRelation = getThroughRelation(table, through);
526
545
  const sourceRelation = getSourceRelation(throughRelation, source);
527
- const sourceQuery = sourceRelation.joinQuery(throughRelation.query, sourceRelation.query).as(relationName);
546
+ const sourceQuery = sourceRelation.joinQuery(sourceRelation.query, throughRelation.query).as(relationName);
528
547
  const whereExistsCallback = () => sourceQuery;
548
+ const reverseJoin2 = (baseQuery, joiningQuery) => {
549
+ return joinHasThrough(
550
+ baseQuery,
551
+ baseQuery,
552
+ joiningQuery,
553
+ throughRelation,
554
+ sourceRelation
555
+ );
556
+ };
529
557
  return {
530
558
  returns: "one",
531
559
  method: (params) => {
@@ -535,24 +563,17 @@ const makeHasOneMethod = (table, relation, relationName, query) => {
535
563
  whereExistsCallback
536
564
  );
537
565
  },
538
- joinQuery(fromQuery, toQuery) {
539
- return joinHasThrough(
540
- toQuery,
541
- fromQuery,
542
- toQuery,
543
- throughRelation,
544
- sourceRelation
545
- );
546
- },
547
- reverseJoin(fromQuery, toQuery) {
548
- return joinHasThrough(
549
- fromQuery,
550
- fromQuery,
551
- toQuery,
566
+ joinQuery: joinQueryChainingHOF(
567
+ reverseJoin2,
568
+ (joiningQuery, baseQuery) => joinHasThrough(
569
+ joiningQuery,
570
+ baseQuery,
571
+ joiningQuery,
552
572
  throughRelation,
553
573
  sourceRelation
554
- );
555
- }
574
+ )
575
+ ),
576
+ reverseJoin: reverseJoin2
556
577
  };
557
578
  }
558
579
  const primaryKeys = "columns" in relation.options ? relation.options.columns : [relation.options.primaryKey];
@@ -564,6 +585,15 @@ const makeHasOneMethod = (table, relation, relationName, query) => {
564
585
  reversedOn[foreignKeys[i]] = primaryKeys[i];
565
586
  }
566
587
  const fromQuerySelect = [{ selectAs: reversedOn }];
588
+ const reverseJoin = (baseQuery, joiningQuery) => {
589
+ return joinHasRelation(
590
+ joiningQuery,
591
+ baseQuery,
592
+ foreignKeys,
593
+ primaryKeys,
594
+ len
595
+ );
596
+ };
567
597
  return {
568
598
  returns: "one",
569
599
  method: (params) => {
@@ -574,19 +604,18 @@ const makeHasOneMethod = (table, relation, relationName, query) => {
574
604
  return query.where(values)._defaults(values);
575
605
  },
576
606
  virtualColumn: new HasOneVirtualColumn(relationName, state),
577
- joinQuery(fromQuery, toQuery) {
578
- return joinHasRelation(fromQuery, toQuery, primaryKeys, foreignKeys, len);
579
- },
580
- reverseJoin(fromQuery, toQuery) {
581
- return joinHasRelation(toQuery, fromQuery, foreignKeys, primaryKeys, len);
582
- },
607
+ joinQuery: joinQueryChainingHOF(
608
+ reverseJoin,
609
+ (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)
610
+ ),
611
+ reverseJoin,
583
612
  modifyRelatedQuery(relationQuery) {
584
613
  return (query2) => {
585
- const fromQuery = query2.clone();
586
- fromQuery.q.select = fromQuerySelect;
614
+ const baseQuery = query2.clone();
615
+ baseQuery.q.select = fromQuerySelect;
587
616
  const q = relationQuery.q;
588
617
  q.kind = "from";
589
- q.values = { from: fromQuery };
618
+ q.values = { from: baseQuery };
590
619
  };
591
620
  }
592
621
  };
@@ -760,10 +789,19 @@ const makeHasManyMethod = (table, relation, relationName, query) => {
760
789
  const sourceRelation = getSourceRelation(throughRelation, source);
761
790
  const sourceRelationQuery = sourceRelation.query.as(relationName);
762
791
  const sourceQuery = sourceRelation.joinQuery(
763
- throughRelation.query,
764
- sourceRelationQuery
792
+ sourceRelationQuery,
793
+ throughRelation.query
765
794
  );
766
795
  const whereExistsCallback = () => sourceQuery;
796
+ const reverseJoin2 = (baseQuery, joiningQuery) => {
797
+ return joinHasThrough(
798
+ baseQuery,
799
+ baseQuery,
800
+ joiningQuery,
801
+ throughRelation,
802
+ sourceRelation
803
+ );
804
+ };
767
805
  return {
768
806
  returns: "many",
769
807
  method: (params) => {
@@ -773,24 +811,17 @@ const makeHasManyMethod = (table, relation, relationName, query) => {
773
811
  whereExistsCallback
774
812
  );
775
813
  },
776
- joinQuery(fromQuery, toQuery) {
777
- return joinHasThrough(
778
- toQuery,
779
- fromQuery,
780
- toQuery,
781
- throughRelation,
782
- sourceRelation
783
- );
784
- },
785
- reverseJoin(fromQuery, toQuery) {
786
- return joinHasThrough(
787
- fromQuery,
788
- fromQuery,
789
- toQuery,
814
+ joinQuery: joinQueryChainingHOF(
815
+ reverseJoin2,
816
+ (joiningQuery, baseQuery) => joinHasThrough(
817
+ joiningQuery,
818
+ baseQuery,
819
+ joiningQuery,
790
820
  throughRelation,
791
821
  sourceRelation
792
- );
793
- }
822
+ )
823
+ ),
824
+ reverseJoin: reverseJoin2
794
825
  };
795
826
  }
796
827
  const primaryKeys = "columns" in relation.options ? relation.options.columns : [relation.options.primaryKey];
@@ -802,6 +833,15 @@ const makeHasManyMethod = (table, relation, relationName, query) => {
802
833
  reversedOn[foreignKeys[i]] = primaryKeys[i];
803
834
  }
804
835
  const fromQuerySelect = [{ selectAs: reversedOn }];
836
+ const reverseJoin = (baseQuery, joiningQuery) => {
837
+ return joinHasRelation(
838
+ joiningQuery,
839
+ baseQuery,
840
+ foreignKeys,
841
+ primaryKeys,
842
+ len
843
+ );
844
+ };
805
845
  return {
806
846
  returns: "many",
807
847
  method: (params) => {
@@ -812,19 +852,18 @@ const makeHasManyMethod = (table, relation, relationName, query) => {
812
852
  return query.where(values)._defaults(values);
813
853
  },
814
854
  virtualColumn: new HasManyVirtualColumn(relationName, state),
815
- joinQuery(fromQuery, toQuery) {
816
- return joinHasRelation(fromQuery, toQuery, primaryKeys, foreignKeys, len);
817
- },
818
- reverseJoin(fromQuery, toQuery) {
819
- return joinHasRelation(toQuery, fromQuery, foreignKeys, primaryKeys, len);
820
- },
855
+ joinQuery: joinQueryChainingHOF(
856
+ reverseJoin,
857
+ (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)
858
+ ),
859
+ reverseJoin,
821
860
  modifyRelatedQuery(relationQuery) {
822
861
  return (query2) => {
823
- const fromQuery = query2.clone();
824
- fromQuery.q.select = fromQuerySelect;
862
+ const baseQuery = query2.clone();
863
+ baseQuery.q.select = fromQuerySelect;
825
864
  const q = relationQuery.q;
826
865
  q.kind = "from";
827
- q.values = { from: fromQuery };
866
+ q.values = { from: baseQuery };
828
867
  };
829
868
  }
830
869
  };
@@ -1096,8 +1135,8 @@ const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query)
1096
1135
  throughForeignKeysFull,
1097
1136
  throughPrimaryKeysFull
1098
1137
  };
1099
- const joinQuery = (toQuery, tableAs, foreignAs) => {
1100
- return toQuery.whereExists(subQuery, (q) => {
1138
+ const joinQuery = (joiningQuery, tableAs, foreignAs) => {
1139
+ return joiningQuery.whereExists(subQuery, (q) => {
1101
1140
  for (let i = 0; i < throughLen; i++) {
1102
1141
  q._on(
1103
1142
  throughForeignKeysFull[i],
@@ -1115,6 +1154,13 @@ const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query)
1115
1154
  obj[foreignKeys[i]] = primaryKeys[i];
1116
1155
  }
1117
1156
  const selectPrimaryKeysAsForeignKeys = [{ selectAs: obj }];
1157
+ const reverseJoin = (baseQuery2, joiningQuery) => {
1158
+ return joinQuery(
1159
+ baseQuery2,
1160
+ pqb.getQueryAs(baseQuery2),
1161
+ pqb.getQueryAs(joiningQuery)
1162
+ );
1163
+ };
1118
1164
  return {
1119
1165
  returns: "many",
1120
1166
  method(params) {
@@ -1131,22 +1177,18 @@ const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query)
1131
1177
  });
1132
1178
  },
1133
1179
  virtualColumn: new HasAndBelongsToManyVirtualColumn(relationName, state),
1134
- // joinQuery can be a property of RelationQuery and be used by whereExists and other stuff which needs it
1135
- // and the chained query itself may be a query around this joinQuery
1136
- joinQuery(fromQuery, toQuery) {
1137
- const join = joinQuery(
1138
- toQuery,
1139
- pqb.getQueryAs(fromQuery),
1140
- pqb.getQueryAs(toQuery)
1180
+ joinQuery: joinQueryChainingHOF(reverseJoin, (joiningQuery, baseQuery2) => {
1181
+ const joined = joinQuery(
1182
+ joiningQuery,
1183
+ pqb.getQueryAs(baseQuery2),
1184
+ pqb.getQueryAs(joiningQuery)
1141
1185
  );
1142
- join.q.joinedShapes = __spreadProps$1(__spreadValues$3({}, join.q.joinedShapes), {
1143
- [fromQuery.q.as || fromQuery.table]: fromQuery.q.shape
1186
+ joined.q.joinedShapes = __spreadProps$1(__spreadValues$3({}, joined.q.joinedShapes), {
1187
+ [baseQuery2.q.as || baseQuery2.table]: baseQuery2.q.shape
1144
1188
  });
1145
- return join;
1146
- },
1147
- reverseJoin(fromQuery, toQuery) {
1148
- return joinQuery(fromQuery, pqb.getQueryAs(fromQuery), pqb.getQueryAs(toQuery));
1149
- },
1189
+ return joined;
1190
+ }),
1191
+ reverseJoin,
1150
1192
  modifyRelatedQuery(relationQuery) {
1151
1193
  const ref = {};
1152
1194
  relationQuery._afterCreate([], async (result) => {
@@ -1156,15 +1198,15 @@ const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query)
1156
1198
  "Creating multiple `hasAndBelongsToMany` records is not yet supported"
1157
1199
  );
1158
1200
  }
1159
- const fromQuery = ref.q.clone();
1160
- fromQuery.q.select = selectPrimaryKeysAsForeignKeys;
1201
+ const baseQuery2 = ref.q.clone();
1202
+ baseQuery2.q.select = selectPrimaryKeysAsForeignKeys;
1161
1203
  const data = {};
1162
1204
  for (let i = 0; i < throughLen; i++) {
1163
1205
  data[throughForeignKeys[i]] = result[0][throughPrimaryKeys[i]];
1164
1206
  }
1165
- const createdCount = await subQuery.count()._createFrom(fromQuery, data);
1207
+ const createdCount = await subQuery.count()._createFrom(baseQuery2, data);
1166
1208
  if (createdCount === 0) {
1167
- throw new pqb.NotFoundError(fromQuery);
1209
+ throw new pqb.NotFoundError(baseQuery2);
1168
1210
  }
1169
1211
  });
1170
1212
  return (q) => {
@@ -1586,10 +1628,23 @@ const makeRelationQuery = (table, relationName, data, q) => {
1586
1628
  get() {
1587
1629
  var _a;
1588
1630
  const toTable = q.clone();
1589
- const query = this.q.isSubQuery ? toTable : toTable._all()._whereExists(
1590
- this.baseQuery,
1591
- (q2) => data.reverseJoin(this, toTable)
1592
- );
1631
+ let query;
1632
+ if (this.q.isSubQuery) {
1633
+ query = toTable;
1634
+ query.q.isSubQuery = true;
1635
+ } else {
1636
+ query = toTable._all()._where({
1637
+ EXISTS: {
1638
+ args: [data.reverseJoin(this, toTable)]
1639
+ }
1640
+ });
1641
+ }
1642
+ if (this.q.relChain) {
1643
+ query.q.relChain = [...this.q.relChain, this];
1644
+ query.q.returnType = "all";
1645
+ } else {
1646
+ query.q.relChain = [this];
1647
+ }
1593
1648
  query.q.joinedShapes = __spreadValues$2({
1594
1649
  [pqb.getQueryAs(this)]: this.q.shape
1595
1650
  }, this.q.joinedShapes);
@@ -1704,7 +1759,8 @@ const orchidORM = (_a, tables) => {
1704
1759
  tableInstances[key] = table;
1705
1760
  const options2 = __spreadProps(__spreadValues$1({}, commonOptions), {
1706
1761
  schema: table.schema,
1707
- language: table.language
1762
+ language: table.language,
1763
+ scopes: table.scopes
1708
1764
  });
1709
1765
  if (table.noPrimaryKey)
1710
1766
  options2.noPrimaryKey = "ignore";