metal-orm 1.0.77 → 1.0.79

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.
@@ -29,17 +29,17 @@ import {
29
29
  SelectQueryBuilderEnvironment
30
30
  } from './select-query-builder-deps.js';
31
31
  import { ColumnSelector } from './column-selector.js';
32
- import { RelationIncludeOptions, RelationTargetColumns, TypedRelationIncludeOptions } from './relation-types.js';
33
- import { RelationKinds } from '../schema/relation.js';
34
- import {
35
- RelationIncludeInput,
36
- RelationIncludeNodeInput,
37
- NormalizedRelationIncludeTree,
38
- cloneRelationIncludeTree,
39
- mergeRelationIncludeTrees,
40
- normalizeRelationInclude,
41
- normalizeRelationIncludeNode
42
- } from './relation-include-tree.js';
32
+ import { RelationIncludeOptions, RelationTargetColumns, TypedRelationIncludeOptions } from './relation-types.js';
33
+ import { RelationKinds } from '../schema/relation.js';
34
+ import {
35
+ RelationIncludeInput,
36
+ RelationIncludeNodeInput,
37
+ NormalizedRelationIncludeTree,
38
+ cloneRelationIncludeTree,
39
+ mergeRelationIncludeTrees,
40
+ normalizeRelationInclude,
41
+ normalizeRelationIncludeNode
42
+ } from './relation-include-tree.js';
43
43
  import { JOIN_KINDS, JoinKind, ORDER_DIRECTIONS, OrderDirection } from '../core/sql/sql.js';
44
44
  import { EntityInstance, RelationMap } from '../schema/types.js';
45
45
  import type { ColumnToTs, InferRow } from '../schema/types.js';
@@ -55,9 +55,11 @@ import {
55
55
  buildWhereHasPredicate,
56
56
  executeCount,
57
57
  executePagedQuery,
58
+ PaginatedResult,
58
59
  RelationCallback,
59
60
  WhereHasOptions
60
61
  } from './select/select-operations.js';
62
+ export type { PaginatedResult };
61
63
  import { SelectFromFacet } from './select/from-facet.js';
62
64
  import { SelectJoinFacet } from './select/join-facet.js';
63
65
  import { SelectProjectionFacet } from './select/projection-facet.js';
@@ -113,11 +115,11 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
113
115
  private readonly predicateFacet: SelectPredicateFacet;
114
116
  private readonly cteFacet: SelectCTEFacet;
115
117
  private readonly setOpFacet: SelectSetOpFacet;
116
- private readonly relationFacet: SelectRelationFacet;
117
- private readonly lazyRelations: Set<string>;
118
- private readonly lazyRelationOptions: Map<string, RelationIncludeOptions>;
119
- private readonly entityConstructor?: EntityConstructor;
120
- private readonly includeTree: NormalizedRelationIncludeTree;
118
+ private readonly relationFacet: SelectRelationFacet;
119
+ private readonly lazyRelations: Set<string>;
120
+ private readonly lazyRelationOptions: Map<string, RelationIncludeOptions>;
121
+ private readonly entityConstructor?: EntityConstructor;
122
+ private readonly includeTree: NormalizedRelationIncludeTree;
121
123
 
122
124
  /**
123
125
  * Creates a new SelectQueryBuilder instance
@@ -126,16 +128,16 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
126
128
  * @param hydration - Optional hydration manager
127
129
  * @param dependencies - Optional query builder dependencies
128
130
  */
129
- constructor(
130
- table: TTable,
131
- state?: SelectQueryState,
132
- hydration?: HydrationManager,
133
- dependencies?: Partial<SelectQueryBuilderDependencies>,
134
- lazyRelations?: Set<string>,
135
- lazyRelationOptions?: Map<string, RelationIncludeOptions>,
136
- entityConstructor?: EntityConstructor,
137
- includeTree?: NormalizedRelationIncludeTree
138
- ) {
131
+ constructor(
132
+ table: TTable,
133
+ state?: SelectQueryState,
134
+ hydration?: HydrationManager,
135
+ dependencies?: Partial<SelectQueryBuilderDependencies>,
136
+ lazyRelations?: Set<string>,
137
+ lazyRelationOptions?: Map<string, RelationIncludeOptions>,
138
+ entityConstructor?: EntityConstructor,
139
+ includeTree?: NormalizedRelationIncludeTree
140
+ ) {
139
141
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
140
142
  this.env = { table, deps };
141
143
  const createAstService = (nextState: SelectQueryState) => deps.createQueryAstService(table, nextState);
@@ -145,11 +147,11 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
145
147
  state: initialState,
146
148
  hydration: initialHydration
147
149
  };
148
- this.lazyRelations = new Set(lazyRelations ?? []);
149
- this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
150
- this.entityConstructor = entityConstructor;
151
- this.includeTree = includeTree ?? {};
152
- this.columnSelector = deps.createColumnSelector(this.env);
150
+ this.lazyRelations = new Set(lazyRelations ?? []);
151
+ this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
152
+ this.entityConstructor = entityConstructor;
153
+ this.includeTree = includeTree ?? {};
154
+ this.columnSelector = deps.createColumnSelector(this.env);
153
155
  const relationManager = deps.createRelationManager(this.env);
154
156
  this.fromFacet = new SelectFromFacet(this.env, createAstService);
155
157
  this.joinFacet = new SelectJoinFacet(this.env, createAstService);
@@ -166,23 +168,23 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
166
168
  * @param lazyRelations - Updated lazy relations set
167
169
  * @returns New SelectQueryBuilder instance
168
170
  */
169
- private clone<TNext = T>(
170
- context: SelectQueryBuilderContext = this.context,
171
- lazyRelations = new Set(this.lazyRelations),
172
- lazyRelationOptions = new Map(this.lazyRelationOptions),
173
- includeTree = this.includeTree
174
- ): SelectQueryBuilder<TNext, TTable> {
175
- return new SelectQueryBuilder(
176
- this.env.table as TTable,
177
- context.state,
178
- context.hydration,
179
- this.env.deps,
180
- lazyRelations,
181
- lazyRelationOptions,
182
- this.entityConstructor,
183
- includeTree
184
- ) as SelectQueryBuilder<TNext, TTable>;
185
- }
171
+ private clone<TNext = T>(
172
+ context: SelectQueryBuilderContext = this.context,
173
+ lazyRelations = new Set(this.lazyRelations),
174
+ lazyRelationOptions = new Map(this.lazyRelationOptions),
175
+ includeTree = this.includeTree
176
+ ): SelectQueryBuilder<TNext, TTable> {
177
+ return new SelectQueryBuilder(
178
+ this.env.table as TTable,
179
+ context.state,
180
+ context.hydration,
181
+ this.env.deps,
182
+ lazyRelations,
183
+ lazyRelationOptions,
184
+ this.entityConstructor,
185
+ includeTree
186
+ ) as SelectQueryBuilder<TNext, TTable>;
187
+ }
186
188
 
187
189
  /**
188
190
  * Applies an alias to the root FROM table.
@@ -562,42 +564,42 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
562
564
  * qb.include('posts');
563
565
  * @example
564
566
  * qb.include('posts', { columns: ['id', 'title', 'published'] });
565
- * @example
566
- * qb.include('posts', {
567
- * columns: ['id', 'title'],
568
- * where: eq(postTable.columns.published, true)
569
- * });
570
- * @example
571
- * qb.include({ posts: { include: { author: true } } });
572
- */
573
- include<K extends keyof TTable['relations'] & string>(
574
- relationName: K,
575
- options?: RelationIncludeNodeInput<TTable['relations'][K]>
576
- ): SelectQueryBuilder<T, TTable>;
577
- include(relations: RelationIncludeInput<TTable>): SelectQueryBuilder<T, TTable>;
578
- include<K extends keyof TTable['relations'] & string>(
579
- relationNameOrRelations: K | RelationIncludeInput<TTable>,
580
- options?: RelationIncludeNodeInput<TTable['relations'][K]>
581
- ): SelectQueryBuilder<T, TTable> {
582
- if (typeof relationNameOrRelations === 'object' && relationNameOrRelations !== null) {
583
- const normalized = normalizeRelationInclude(relationNameOrRelations as RelationIncludeInput<TableDef>);
584
- let nextContext = this.context;
585
- for (const [relationName, node] of Object.entries(normalized)) {
586
- nextContext = this.relationFacet.include(nextContext, relationName, node.options);
587
- }
588
- const nextTree = mergeRelationIncludeTrees(this.includeTree, normalized);
589
- return this.clone(nextContext, undefined, undefined, nextTree);
590
- }
591
-
592
- const relationName = relationNameOrRelations as string;
593
- const normalizedNode = normalizeRelationIncludeNode(options);
594
- const nextContext = this.relationFacet.include(this.context, relationName, normalizedNode.options);
595
- const shouldStore = Boolean(normalizedNode.include || normalizedNode.options);
596
- const nextTree = shouldStore
597
- ? mergeRelationIncludeTrees(this.includeTree, { [relationName]: normalizedNode })
598
- : this.includeTree;
599
- return this.clone(nextContext, undefined, undefined, nextTree);
600
- }
567
+ * @example
568
+ * qb.include('posts', {
569
+ * columns: ['id', 'title'],
570
+ * where: eq(postTable.columns.published, true)
571
+ * });
572
+ * @example
573
+ * qb.include({ posts: { include: { author: true } } });
574
+ */
575
+ include<K extends keyof TTable['relations'] & string>(
576
+ relationName: K,
577
+ options?: RelationIncludeNodeInput<TTable['relations'][K]>
578
+ ): SelectQueryBuilder<T, TTable>;
579
+ include(relations: RelationIncludeInput<TTable>): SelectQueryBuilder<T, TTable>;
580
+ include<K extends keyof TTable['relations'] & string>(
581
+ relationNameOrRelations: K | RelationIncludeInput<TTable>,
582
+ options?: RelationIncludeNodeInput<TTable['relations'][K]>
583
+ ): SelectQueryBuilder<T, TTable> {
584
+ if (typeof relationNameOrRelations === 'object' && relationNameOrRelations !== null) {
585
+ const normalized = normalizeRelationInclude(relationNameOrRelations as RelationIncludeInput<TableDef>);
586
+ let nextContext = this.context;
587
+ for (const [relationName, node] of Object.entries(normalized)) {
588
+ nextContext = this.relationFacet.include(nextContext, relationName, node.options);
589
+ }
590
+ const nextTree = mergeRelationIncludeTrees(this.includeTree, normalized);
591
+ return this.clone(nextContext, undefined, undefined, nextTree);
592
+ }
593
+
594
+ const relationName = relationNameOrRelations as string;
595
+ const normalizedNode = normalizeRelationIncludeNode(options);
596
+ const nextContext = this.relationFacet.include(this.context, relationName, normalizedNode.options);
597
+ const shouldStore = Boolean(normalizedNode.include || normalizedNode.options);
598
+ const nextTree = shouldStore
599
+ ? mergeRelationIncludeTrees(this.includeTree, { [relationName]: normalizedNode })
600
+ : this.includeTree;
601
+ return this.clone(nextContext, undefined, undefined, nextTree);
602
+ }
601
603
 
602
604
  /**
603
605
  * Includes a relation lazily in the query results
@@ -645,13 +647,13 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
645
647
  * @example
646
648
  * qb.includePick('posts', ['id', 'title', 'createdAt']);
647
649
  */
648
- includePick<
649
- K extends keyof TTable['relations'] & string,
650
- C extends RelationTargetColumns<TTable['relations'][K]>
651
- >(relationName: K, cols: C[]): SelectQueryBuilder<T, TTable> {
652
- const options = { columns: cols as readonly C[] } as unknown as RelationIncludeNodeInput<TTable['relations'][K]>;
653
- return this.include(relationName, options);
654
- }
650
+ includePick<
651
+ K extends keyof TTable['relations'] & string,
652
+ C extends RelationTargetColumns<TTable['relations'][K]>
653
+ >(relationName: K, cols: C[]): SelectQueryBuilder<T, TTable> {
654
+ const options = { columns: cols as readonly C[] } as unknown as RelationIncludeNodeInput<TTable['relations'][K]>;
655
+ return this.include(relationName, options);
656
+ }
655
657
 
656
658
  /**
657
659
  * Selects columns for the root table and relations from an array of entries
@@ -668,13 +670,13 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
668
670
  let currBuilder: SelectQueryBuilder<T, TTable> = this;
669
671
 
670
672
  for (const entry of config) {
671
- if (entry.type === 'root') {
672
- currBuilder = currBuilder.select(...entry.columns);
673
- } else {
674
- const options = { columns: entry.columns } as unknown as RelationIncludeNodeInput<TTable['relations'][typeof entry.relationName]>;
675
- currBuilder = currBuilder.include(entry.relationName, options);
676
- }
677
- }
673
+ if (entry.type === 'root') {
674
+ currBuilder = currBuilder.select(...entry.columns);
675
+ } else {
676
+ const options = { columns: entry.columns } as unknown as RelationIncludeNodeInput<TTable['relations'][typeof entry.relationName]>;
677
+ currBuilder = currBuilder.include(entry.relationName, options);
678
+ }
679
+ }
678
680
 
679
681
  return currBuilder;
680
682
  }
@@ -691,16 +693,16 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
691
693
  * Gets lazy relation include options
692
694
  * @returns Map of relation names to include options
693
695
  */
694
- getLazyRelationOptions(): Map<string, RelationIncludeOptions> {
695
- return new Map(this.lazyRelationOptions);
696
- }
697
-
698
- /**
699
- * Gets normalized nested include information for runtime preloading.
700
- */
701
- getIncludeTree(): NormalizedRelationIncludeTree {
702
- return cloneRelationIncludeTree(this.includeTree);
703
- }
696
+ getLazyRelationOptions(): Map<string, RelationIncludeOptions> {
697
+ return new Map(this.lazyRelationOptions);
698
+ }
699
+
700
+ /**
701
+ * Gets normalized nested include information for runtime preloading.
702
+ */
703
+ getIncludeTree(): NormalizedRelationIncludeTree {
704
+ return cloneRelationIncludeTree(this.includeTree);
705
+ }
704
706
 
705
707
  /**
706
708
  * Gets the table definition for this query builder
@@ -796,14 +798,14 @@ export class SelectQueryBuilder<T = EntityInstance<TableDef>, TTable extends Tab
796
798
  * Executes the query and returns both the paged items and the total.
797
799
  *
798
800
  * @example
799
- * const { items, totalItems } = await qb.executePaged(session, { page: 1, pageSize: 20 });
801
+ * const { items, totalItems, page, pageSize } = await qb.executePaged(session, { page: 1, pageSize: 20 });
800
802
  */
801
803
  async executePaged(
802
804
  session: OrmSession,
803
805
  options: { page: number; pageSize: number }
804
- ): Promise<{ items: T[]; totalItems: number }> {
806
+ ): Promise<PaginatedResult<T>> {
805
807
  const builder = this.ensureDefaultSelection();
806
- return executePagedQuery(builder, session, options, sess => this.count(sess));
808
+ return executePagedQuery(builder, session, options, sess => builder.count(sess));
807
809
  }
808
810
 
809
811
  /**