metal-orm 1.0.59 → 1.0.62

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.js CHANGED
@@ -5970,6 +5970,132 @@ var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOp
5970
5970
  }
5971
5971
  };
5972
5972
 
5973
+ // src/orm/entity-metadata.ts
5974
+ var metadataMap = /* @__PURE__ */ new Map();
5975
+ var ensureEntityMetadata = (target) => {
5976
+ let meta = metadataMap.get(target);
5977
+ if (!meta) {
5978
+ meta = {
5979
+ target,
5980
+ tableName: target.name || "unknown",
5981
+ columns: {},
5982
+ relations: {}
5983
+ };
5984
+ metadataMap.set(target, meta);
5985
+ }
5986
+ return meta;
5987
+ };
5988
+ var getEntityMetadata = (target) => {
5989
+ return metadataMap.get(target);
5990
+ };
5991
+ var getAllEntityMetadata = () => {
5992
+ return Array.from(metadataMap.values());
5993
+ };
5994
+ var addColumnMetadata = (target, propertyKey, column) => {
5995
+ const meta = ensureEntityMetadata(target);
5996
+ meta.columns[propertyKey] = { ...column };
5997
+ };
5998
+ var addRelationMetadata = (target, propertyKey, relation) => {
5999
+ const meta = ensureEntityMetadata(target);
6000
+ meta.relations[propertyKey] = relation;
6001
+ };
6002
+ var setEntityTableName = (target, tableName, hooks) => {
6003
+ const meta = ensureEntityMetadata(target);
6004
+ if (tableName && tableName.length > 0) {
6005
+ meta.tableName = tableName;
6006
+ }
6007
+ if (hooks) {
6008
+ meta.hooks = hooks;
6009
+ }
6010
+ };
6011
+ var buildTableDef = (meta) => {
6012
+ if (meta.table) {
6013
+ return meta.table;
6014
+ }
6015
+ const columns = {};
6016
+ for (const [key, def] of Object.entries(meta.columns)) {
6017
+ columns[key] = {
6018
+ ...def,
6019
+ name: key,
6020
+ table: meta.tableName
6021
+ };
6022
+ }
6023
+ const table = defineTable(meta.tableName, columns, {}, meta.hooks);
6024
+ meta.table = table;
6025
+ return table;
6026
+ };
6027
+
6028
+ // src/orm/entity-registry.ts
6029
+ var tableToConstructor = /* @__PURE__ */ new Map();
6030
+ var rebuildRegistry = () => {
6031
+ tableToConstructor.clear();
6032
+ for (const meta of getAllEntityMetadata()) {
6033
+ if (meta.table) {
6034
+ tableToConstructor.set(meta.table, meta.target);
6035
+ }
6036
+ }
6037
+ };
6038
+
6039
+ // src/orm/entity-materializer.ts
6040
+ var PrototypeMaterializationStrategy = class {
6041
+ materialize(ctor, data) {
6042
+ const instance = Object.create(ctor.prototype);
6043
+ Object.assign(instance, data);
6044
+ return instance;
6045
+ }
6046
+ };
6047
+ var ConstructorMaterializationStrategy = class {
6048
+ materialize(ctor, data) {
6049
+ const instance = Reflect.construct(ctor, []);
6050
+ Object.assign(instance, data);
6051
+ return instance;
6052
+ }
6053
+ };
6054
+ var DefaultEntityMaterializer = class {
6055
+ constructor(strategy = new ConstructorMaterializationStrategy()) {
6056
+ this.strategy = strategy;
6057
+ }
6058
+ materialize(ctor, row) {
6059
+ const instance = this.strategy.materialize(ctor, row);
6060
+ this.materializeRelations(instance, ctor);
6061
+ return instance;
6062
+ }
6063
+ materializeMany(ctor, rows) {
6064
+ return rows.map((row) => this.materialize(ctor, row));
6065
+ }
6066
+ /**
6067
+ * Recursively materializes nested relation data.
6068
+ */
6069
+ materializeRelations(instance, _ctor) {
6070
+ rebuildRegistry();
6071
+ for (const [key, value] of Object.entries(instance)) {
6072
+ if (value === null || value === void 0) continue;
6073
+ if (typeof value === "object" && !Array.isArray(value)) {
6074
+ const nested = value;
6075
+ if (this.isEntityLike(nested)) {
6076
+ }
6077
+ }
6078
+ if (Array.isArray(value) && value.length > 0) {
6079
+ const first = value[0];
6080
+ if (typeof first === "object" && first !== null && this.isEntityLike(first)) {
6081
+ }
6082
+ }
6083
+ }
6084
+ }
6085
+ /**
6086
+ * Simple heuristic to check if an object looks like an entity.
6087
+ */
6088
+ isEntityLike(obj) {
6089
+ return "id" in obj || Object.keys(obj).some(
6090
+ (k) => k.endsWith("Id") || k === "createdAt" || k === "updatedAt"
6091
+ );
6092
+ }
6093
+ };
6094
+ var materializeAs = (ctor, results) => {
6095
+ const materializer = new DefaultEntityMaterializer();
6096
+ return materializer.materializeMany(ctor, results);
6097
+ };
6098
+
5973
6099
  // src/query-builder/query-resolution.ts
5974
6100
  function resolveSelectQuery(query) {
5975
6101
  const candidate = query;
@@ -6380,6 +6506,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6380
6506
  relationFacet;
6381
6507
  lazyRelations;
6382
6508
  lazyRelationOptions;
6509
+ entityConstructor;
6383
6510
  /**
6384
6511
  * Creates a new SelectQueryBuilder instance
6385
6512
  * @param table - Table definition to query
@@ -6387,7 +6514,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6387
6514
  * @param hydration - Optional hydration manager
6388
6515
  * @param dependencies - Optional query builder dependencies
6389
6516
  */
6390
- constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions) {
6517
+ constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions, entityConstructor) {
6391
6518
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
6392
6519
  this.env = { table, deps };
6393
6520
  const createAstService = (nextState) => deps.createQueryAstService(table, nextState);
@@ -6399,6 +6526,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6399
6526
  };
6400
6527
  this.lazyRelations = new Set(lazyRelations ?? []);
6401
6528
  this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
6529
+ this.entityConstructor = entityConstructor;
6402
6530
  this.columnSelector = deps.createColumnSelector(this.env);
6403
6531
  const relationManager = deps.createRelationManager(this.env);
6404
6532
  this.fromFacet = new SelectFromFacet(this.env, createAstService);
@@ -6422,12 +6550,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6422
6550
  context.hydration,
6423
6551
  this.env.deps,
6424
6552
  lazyRelations,
6425
- lazyRelationOptions
6553
+ lazyRelationOptions,
6554
+ this.entityConstructor
6426
6555
  );
6427
6556
  }
6428
6557
  /**
6429
6558
  * Applies an alias to the root FROM table.
6430
6559
  * @param alias - Alias to apply
6560
+ * @example
6561
+ * const qb = new SelectQueryBuilder(userTable).as('u');
6431
6562
  */
6432
6563
  as(alias) {
6433
6564
  const nextContext = this.fromFacet.as(this.context, alias);
@@ -6485,6 +6616,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6485
6616
  * Selects raw column expressions
6486
6617
  * @param cols - Column expressions as strings
6487
6618
  * @returns New query builder instance with raw column selections
6619
+ * @example
6620
+ * qb.selectRaw('COUNT(*) as total', 'UPPER(name) as upper_name');
6488
6621
  */
6489
6622
  selectRaw(...cols) {
6490
6623
  return this.clone(this.projectionFacet.selectRaw(this.context, cols));
@@ -6495,6 +6628,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6495
6628
  * @param query - Query builder or query node for the CTE
6496
6629
  * @param columns - Optional column names for the CTE
6497
6630
  * @returns New query builder instance with the CTE
6631
+ * @example
6632
+ * const recentUsers = new SelectQueryBuilder(userTable)
6633
+ * .where(gt(userTable.columns.createdAt, subDays(now(), 30)));
6634
+ * const qb = new SelectQueryBuilder(userTable)
6635
+ * .with('recent_users', recentUsers)
6636
+ * .from('recent_users');
6498
6637
  */
6499
6638
  with(name, query, columns) {
6500
6639
  const subAst = resolveSelectQuery(query);
@@ -6507,6 +6646,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6507
6646
  * @param query - Query builder or query node for the CTE
6508
6647
  * @param columns - Optional column names for the CTE
6509
6648
  * @returns New query builder instance with the recursive CTE
6649
+ * @example
6650
+ * // Base case: select root nodes
6651
+ * const baseQuery = new SelectQueryBuilder(orgTable)
6652
+ * .where(eq(orgTable.columns.parentId, 1));
6653
+ * // Recursive case: join with the CTE itself
6654
+ * const recursiveQuery = new SelectQueryBuilder(orgTable)
6655
+ * .join('org_hierarchy', 'oh', eq(orgTable.columns.parentId, col('oh.id')));
6656
+ * // Combine base and recursive parts
6657
+ * const orgHierarchy = baseQuery.union(recursiveQuery);
6658
+ * // Use in main query
6659
+ * const qb = new SelectQueryBuilder(orgTable)
6660
+ * .withRecursive('org_hierarchy', orgHierarchy)
6661
+ * .from('org_hierarchy');
6510
6662
  */
6511
6663
  withRecursive(name, query, columns) {
6512
6664
  const subAst = resolveSelectQuery(query);
@@ -6519,6 +6671,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6519
6671
  * @param alias - Alias for the derived table
6520
6672
  * @param columnAliases - Optional column alias list
6521
6673
  * @returns New query builder instance with updated FROM
6674
+ * @example
6675
+ * const subquery = new SelectQueryBuilder(userTable)
6676
+ * .select('id', 'name')
6677
+ * .where(gt(userTable.columns.score, 100));
6678
+ * qb.fromSubquery(subquery, 'high_scorers', ['userId', 'userName']);
6522
6679
  */
6523
6680
  fromSubquery(subquery, alias, columnAliases) {
6524
6681
  const subAst = resolveSelectQuery(subquery);
@@ -6531,6 +6688,13 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6531
6688
  * @param args - Optional function arguments
6532
6689
  * @param alias - Optional alias for the function table
6533
6690
  * @param options - Optional function-table metadata (lateral, ordinality, column aliases, schema)
6691
+ * @example
6692
+ * qb.fromFunctionTable(
6693
+ * 'generate_series',
6694
+ * [literal(1), literal(10), literal(1)],
6695
+ * 'series',
6696
+ * { columnAliases: ['value'] }
6697
+ * );
6534
6698
  */
6535
6699
  fromFunctionTable(name, args = [], alias, options) {
6536
6700
  const nextContext = this.fromFacet.fromFunctionTable(this.context, name, args, alias, options);
@@ -6541,6 +6705,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6541
6705
  * @param alias - Alias for the subquery column
6542
6706
  * @param sub - Query builder or query node for the subquery
6543
6707
  * @returns New query builder instance with the subquery selection
6708
+ * @example
6709
+ * const postCount = new SelectQueryBuilder(postTable)
6710
+ * .select(count(postTable.columns.id))
6711
+ * .where(eq(postTable.columns.userId, col('u.id')));
6712
+ * qb.select('id', 'name')
6713
+ * .selectSubquery('postCount', postCount);
6544
6714
  */
6545
6715
  selectSubquery(alias, sub2) {
6546
6716
  const query = resolveSelectQuery(sub2);
@@ -6554,6 +6724,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6554
6724
  * @param joinKind - Join kind (defaults to INNER)
6555
6725
  * @param columnAliases - Optional column alias list for the derived table
6556
6726
  * @returns New query builder instance with the derived-table join
6727
+ * @example
6728
+ * const activeUsers = new SelectQueryBuilder(userTable)
6729
+ * .where(eq(userTable.columns.active, true));
6730
+ * qb.joinSubquery(
6731
+ * activeUsers,
6732
+ * 'au',
6733
+ * eq(col('t.userId'), col('au.id')),
6734
+ * JOIN_KINDS.LEFT
6735
+ * );
6557
6736
  */
6558
6737
  joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
6559
6738
  const subAst = resolveSelectQuery(subquery);
@@ -6568,6 +6747,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6568
6747
  * @param condition - Join condition expression
6569
6748
  * @param joinKind - Kind of join (defaults to INNER)
6570
6749
  * @param options - Optional metadata (lateral, ordinality, column aliases, schema)
6750
+ * @example
6751
+ * qb.joinFunctionTable(
6752
+ * 'generate_series',
6753
+ * [literal(1), literal(10)],
6754
+ * 'gs',
6755
+ * eq(col('t.value'), col('gs.value')),
6756
+ * JOIN_KINDS.INNER,
6757
+ * { columnAliases: ['value'] }
6758
+ * );
6571
6759
  */
6572
6760
  joinFunctionTable(name, args = [], alias, condition, joinKind = JOIN_KINDS.INNER, options) {
6573
6761
  const nextContext = this.joinFacet.joinFunctionTable(this.context, name, args, alias, condition, joinKind, options);
@@ -6578,6 +6766,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6578
6766
  * @param table - Table to join
6579
6767
  * @param condition - Join condition expression
6580
6768
  * @returns New query builder instance with the INNER JOIN
6769
+ * @example
6770
+ * qb.innerJoin(
6771
+ * postTable,
6772
+ * eq(userTable.columns.id, postTable.columns.userId)
6773
+ * );
6581
6774
  */
6582
6775
  innerJoin(table, condition) {
6583
6776
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
@@ -6588,6 +6781,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6588
6781
  * @param table - Table to join
6589
6782
  * @param condition - Join condition expression
6590
6783
  * @returns New query builder instance with the LEFT JOIN
6784
+ * @example
6785
+ * qb.leftJoin(
6786
+ * postTable,
6787
+ * eq(userTable.columns.id, postTable.columns.userId)
6788
+ * );
6591
6789
  */
6592
6790
  leftJoin(table, condition) {
6593
6791
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
@@ -6598,6 +6796,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6598
6796
  * @param table - Table to join
6599
6797
  * @param condition - Join condition expression
6600
6798
  * @returns New query builder instance with the RIGHT JOIN
6799
+ * @example
6800
+ * qb.rightJoin(
6801
+ * postTable,
6802
+ * eq(userTable.columns.id, postTable.columns.userId)
6803
+ * );
6601
6804
  */
6602
6805
  rightJoin(table, condition) {
6603
6806
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
@@ -6608,6 +6811,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6608
6811
  * @param relationName - Name of the relationship to match
6609
6812
  * @param predicate - Optional predicate expression
6610
6813
  * @returns New query builder instance with the relationship match
6814
+ * @example
6815
+ * qb.match('posts', eq(postTable.columns.published, true));
6611
6816
  */
6612
6817
  match(relationName, predicate) {
6613
6818
  const nextContext = this.relationFacet.match(this.context, relationName, predicate);
@@ -6619,6 +6824,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6619
6824
  * @param joinKind - Type of join (defaults to INNER)
6620
6825
  * @param extraCondition - Optional additional join condition
6621
6826
  * @returns New query builder instance with the relationship join
6827
+ * @example
6828
+ * qb.joinRelation('posts', JOIN_KINDS.LEFT);
6829
+ * @example
6830
+ * qb.joinRelation('posts', JOIN_KINDS.INNER, eq(postTable.columns.published, true));
6622
6831
  */
6623
6832
  joinRelation(relationName, joinKind = JOIN_KINDS.INNER, extraCondition) {
6624
6833
  const nextContext = this.relationFacet.joinRelation(this.context, relationName, joinKind, extraCondition);
@@ -6629,6 +6838,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6629
6838
  * @param relationName - Name of the relationship to include
6630
6839
  * @param options - Optional include options
6631
6840
  * @returns New query builder instance with the relationship inclusion
6841
+ * @example
6842
+ * qb.include('posts');
6843
+ * @example
6844
+ * qb.include('posts', { columns: ['id', 'title', 'published'] });
6845
+ * @example
6846
+ * qb.include('posts', {
6847
+ * columns: ['id', 'title'],
6848
+ * where: eq(postTable.columns.published, true)
6849
+ * });
6632
6850
  */
6633
6851
  include(relationName, options) {
6634
6852
  const nextContext = this.relationFacet.include(this.context, relationName, options);
@@ -6639,6 +6857,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6639
6857
  * @param relationName - Name of the relation to include lazily
6640
6858
  * @param options - Optional include options for lazy loading
6641
6859
  * @returns New query builder instance with lazy relation inclusion
6860
+ * @example
6861
+ * const qb = new SelectQueryBuilder(userTable).includeLazy('posts');
6862
+ * const users = await qb.execute(session);
6863
+ * // Access posts later - they will be loaded on demand
6864
+ * const posts = await users[0].posts;
6642
6865
  */
6643
6866
  includeLazy(relationName, options) {
6644
6867
  let nextContext = this.context;
@@ -6668,6 +6891,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6668
6891
  }
6669
6892
  /**
6670
6893
  * Convenience alias for including only specific columns from a relation.
6894
+ * @example
6895
+ * qb.includePick('posts', ['id', 'title', 'createdAt']);
6671
6896
  */
6672
6897
  includePick(relationName, cols) {
6673
6898
  const options = { columns: cols };
@@ -6677,6 +6902,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6677
6902
  * Selects columns for the root table and relations from an array of entries
6678
6903
  * @param config - Configuration array for deep column selection
6679
6904
  * @returns New query builder instance with deep column selections
6905
+ * @example
6906
+ * qb.selectColumnsDeep([
6907
+ * { type: 'root', columns: ['id', 'name'] },
6908
+ * { type: 'relation', relationName: 'posts', columns: ['id', 'title'] }
6909
+ * ]);
6680
6910
  */
6681
6911
  selectColumnsDeep(config) {
6682
6912
  let currBuilder = this;
@@ -6712,12 +6942,67 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6712
6942
  return this.env.table;
6713
6943
  }
6714
6944
  /**
6715
- * Executes the query and returns hydrated results
6945
+ * Ensures that if no columns are selected, all columns from the table are selected by default.
6946
+ */
6947
+ ensureDefaultSelection() {
6948
+ const columns = this.context.state.ast.columns;
6949
+ if (!columns || columns.length === 0) {
6950
+ return this.select(...Object.keys(this.env.table.columns));
6951
+ }
6952
+ return this;
6953
+ }
6954
+ /**
6955
+ * Executes the query and returns hydrated results.
6956
+ * If the builder was created with an entity constructor (e.g. via selectFromEntity),
6957
+ * this will automatically return fully materialized entity instances.
6958
+ *
6716
6959
  * @param ctx - ORM session context
6717
- * @returns Promise of entity instances
6960
+ * @returns Promise of entity instances (or objects if generic T is not an entity)
6961
+ * @example
6962
+ * const users = await selectFromEntity(User).execute(session);
6963
+ * // users is User[]
6964
+ * users[0] instanceof User; // true
6718
6965
  */
6719
6966
  async execute(ctx) {
6720
- return executeHydrated(ctx, this);
6967
+ if (this.entityConstructor) {
6968
+ return this.executeAs(this.entityConstructor, ctx);
6969
+ }
6970
+ const builder = this.ensureDefaultSelection();
6971
+ return executeHydrated(ctx, builder);
6972
+ }
6973
+ /**
6974
+ * Executes the query and returns plain row objects (POJOs), ignoring any entity materialization.
6975
+ * Use this if you want raw data even when using selectFromEntity.
6976
+ *
6977
+ * @param ctx - ORM session context
6978
+ * @returns Promise of plain entity instances
6979
+ * @example
6980
+ * const rows = await selectFromEntity(User).executePlain(session);
6981
+ * // rows is EntityInstance<UserTable>[] (plain objects)
6982
+ * rows[0] instanceof User; // false
6983
+ */
6984
+ async executePlain(ctx) {
6985
+ const builder = this.ensureDefaultSelection();
6986
+ return executeHydrated(ctx, builder);
6987
+ }
6988
+ /**
6989
+ * Executes the query and returns results as real class instances.
6990
+ * Unlike execute(), this returns actual instances of the decorated entity class
6991
+ * with working methods and proper instanceof checks.
6992
+ * @param entityClass - The entity class constructor
6993
+ * @param ctx - ORM session context
6994
+ * @returns Promise of entity class instances
6995
+ * @example
6996
+ * const users = await selectFromEntity(User)
6997
+ * .include('posts')
6998
+ * .executeAs(User, session);
6999
+ * users[0] instanceof User; // true!
7000
+ * users[0].getFullName(); // works!
7001
+ */
7002
+ async executeAs(entityClass, ctx) {
7003
+ const builder = this.ensureDefaultSelection();
7004
+ const results = await executeHydrated(ctx, builder);
7005
+ return materializeAs(entityClass, results);
6721
7006
  }
6722
7007
  /**
6723
7008
  * Executes a count query for the current builder without LIMIT/OFFSET clauses.
@@ -6735,21 +7020,38 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6735
7020
  * const { items, totalItems } = await qb.executePaged(session, { page: 1, pageSize: 20 });
6736
7021
  */
6737
7022
  async executePaged(session, options) {
6738
- return executePagedQuery(this, session, options, (sess) => this.count(sess));
7023
+ const builder = this.ensureDefaultSelection();
7024
+ return executePagedQuery(builder, session, options, (sess) => this.count(sess));
6739
7025
  }
6740
7026
  /**
6741
7027
  * Executes the query with provided execution and hydration contexts
6742
7028
  * @param execCtx - Execution context
6743
7029
  * @param hydCtx - Hydration context
6744
7030
  * @returns Promise of entity instances
7031
+ * @example
7032
+ * const execCtx = new ExecutionContext(session);
7033
+ * const hydCtx = new HydrationContext();
7034
+ * const users = await qb.executeWithContexts(execCtx, hydCtx);
6745
7035
  */
6746
7036
  async executeWithContexts(execCtx, hydCtx) {
6747
- return executeHydratedWithContexts(execCtx, hydCtx, this);
7037
+ const builder = this.ensureDefaultSelection();
7038
+ const results = await executeHydratedWithContexts(execCtx, hydCtx, builder);
7039
+ if (this.entityConstructor) {
7040
+ return materializeAs(this.entityConstructor, results);
7041
+ }
7042
+ return results;
6748
7043
  }
6749
7044
  /**
6750
7045
  * Adds a WHERE condition to the query
6751
7046
  * @param expr - Expression for the WHERE clause
6752
7047
  * @returns New query builder instance with the WHERE condition
7048
+ * @example
7049
+ * qb.where(eq(userTable.columns.id, 1));
7050
+ * @example
7051
+ * qb.where(and(
7052
+ * eq(userTable.columns.active, true),
7053
+ * gt(userTable.columns.createdAt, subDays(now(), 30))
7054
+ * ));
6753
7055
  */
6754
7056
  where(expr) {
6755
7057
  const nextContext = this.predicateFacet.where(this.context, expr);
@@ -6759,6 +7061,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6759
7061
  * Adds a GROUP BY clause to the query
6760
7062
  * @param term - Column definition or ordering term to group by
6761
7063
  * @returns New query builder instance with the GROUP BY clause
7064
+ * @example
7065
+ * qb.select('departmentId', count(userTable.columns.id))
7066
+ * .groupBy(userTable.columns.departmentId);
6762
7067
  */
6763
7068
  groupBy(term) {
6764
7069
  const nextContext = this.predicateFacet.groupBy(this.context, term);
@@ -6768,6 +7073,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6768
7073
  * Adds a HAVING condition to the query
6769
7074
  * @param expr - Expression for the HAVING clause
6770
7075
  * @returns New query builder instance with the HAVING condition
7076
+ * @example
7077
+ * qb.select('departmentId', count(userTable.columns.id))
7078
+ * .groupBy(userTable.columns.departmentId)
7079
+ * .having(gt(count(userTable.columns.id), 5));
6771
7080
  */
6772
7081
  having(expr) {
6773
7082
  const nextContext = this.predicateFacet.having(this.context, expr);
@@ -6790,6 +7099,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6790
7099
  * Adds a DISTINCT clause to the query
6791
7100
  * @param cols - Columns to make distinct
6792
7101
  * @returns New query builder instance with the DISTINCT clause
7102
+ * @example
7103
+ * qb.distinct(userTable.columns.email);
7104
+ * @example
7105
+ * qb.distinct(userTable.columns.firstName, userTable.columns.lastName);
6793
7106
  */
6794
7107
  distinct(...cols) {
6795
7108
  return this.clone(this.projectionFacet.distinct(this.context, cols));
@@ -6798,6 +7111,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6798
7111
  * Adds a LIMIT clause to the query
6799
7112
  * @param n - Maximum number of rows to return
6800
7113
  * @returns New query builder instance with the LIMIT clause
7114
+ * @example
7115
+ * qb.limit(10);
7116
+ * @example
7117
+ * qb.limit(20).offset(40); // Pagination: page 3 with 20 items per page
6801
7118
  */
6802
7119
  limit(n) {
6803
7120
  const nextContext = this.predicateFacet.limit(this.context, n);
@@ -6807,6 +7124,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6807
7124
  * Adds an OFFSET clause to the query
6808
7125
  * @param n - Number of rows to skip
6809
7126
  * @returns New query builder instance with the OFFSET clause
7127
+ * @example
7128
+ * qb.offset(10);
7129
+ * @example
7130
+ * qb.limit(20).offset(40); // Pagination: page 3 with 20 items per page
6810
7131
  */
6811
7132
  offset(n) {
6812
7133
  const nextContext = this.predicateFacet.offset(this.context, n);
@@ -6816,6 +7137,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6816
7137
  * Combines this query with another using UNION
6817
7138
  * @param query - Query to union with
6818
7139
  * @returns New query builder instance with the set operation
7140
+ * @example
7141
+ * const activeUsers = new SelectQueryBuilder(userTable)
7142
+ * .where(eq(userTable.columns.active, true));
7143
+ * const inactiveUsers = new SelectQueryBuilder(userTable)
7144
+ * .where(eq(userTable.columns.active, false));
7145
+ * qb.union(activeUsers).union(inactiveUsers);
6819
7146
  */
6820
7147
  union(query) {
6821
7148
  return this.clone(this.applySetOperation("UNION", query));
@@ -6824,6 +7151,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6824
7151
  * Combines this query with another using UNION ALL
6825
7152
  * @param query - Query to union with
6826
7153
  * @returns New query builder instance with the set operation
7154
+ * @example
7155
+ * const q1 = new SelectQueryBuilder(userTable).where(gt(userTable.columns.score, 80));
7156
+ * const q2 = new SelectQueryBuilder(userTable).where(lt(userTable.columns.score, 20));
7157
+ * qb.unionAll(q1).unionAll(q2);
6827
7158
  */
6828
7159
  unionAll(query) {
6829
7160
  return this.clone(this.applySetOperation("UNION ALL", query));
@@ -6832,6 +7163,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6832
7163
  * Combines this query with another using INTERSECT
6833
7164
  * @param query - Query to intersect with
6834
7165
  * @returns New query builder instance with the set operation
7166
+ * @example
7167
+ * const activeUsers = new SelectQueryBuilder(userTable)
7168
+ * .where(eq(userTable.columns.active, true));
7169
+ * const premiumUsers = new SelectQueryBuilder(userTable)
7170
+ * .where(eq(userTable.columns.premium, true));
7171
+ * qb.intersect(activeUsers).intersect(premiumUsers);
6835
7172
  */
6836
7173
  intersect(query) {
6837
7174
  return this.clone(this.applySetOperation("INTERSECT", query));
@@ -6840,6 +7177,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6840
7177
  * Combines this query with another using EXCEPT
6841
7178
  * @param query - Query to subtract
6842
7179
  * @returns New query builder instance with the set operation
7180
+ * @example
7181
+ * const allUsers = new SelectQueryBuilder(userTable);
7182
+ * const inactiveUsers = new SelectQueryBuilder(userTable)
7183
+ * .where(eq(userTable.columns.active, false));
7184
+ * qb.except(allUsers).except(inactiveUsers); // Only active users
6843
7185
  */
6844
7186
  except(query) {
6845
7187
  return this.clone(this.applySetOperation("EXCEPT", query));
@@ -6848,6 +7190,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6848
7190
  * Adds a WHERE EXISTS condition to the query
6849
7191
  * @param subquery - Subquery to check for existence
6850
7192
  * @returns New query builder instance with the WHERE EXISTS condition
7193
+ * @example
7194
+ * const postsQuery = new SelectQueryBuilder(postTable)
7195
+ * .where(eq(postTable.columns.userId, col('u.id')));
7196
+ * qb.whereExists(postsQuery);
6851
7197
  */
6852
7198
  whereExists(subquery, correlate) {
6853
7199
  const subAst = resolveSelectQuery(subquery);
@@ -6858,6 +7204,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6858
7204
  * Adds a WHERE NOT EXISTS condition to the query
6859
7205
  * @param subquery - Subquery to check for non-existence
6860
7206
  * @returns New query builder instance with the WHERE NOT EXISTS condition
7207
+ * @example
7208
+ * const postsQuery = new SelectQueryBuilder(postTable)
7209
+ * .where(eq(postTable.columns.userId, col('u.id')));
7210
+ * qb.whereNotExists(postsQuery); // Users without posts
6861
7211
  */
6862
7212
  whereNotExists(subquery, correlate) {
6863
7213
  const subAst = resolveSelectQuery(subquery);
@@ -6912,6 +7262,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6912
7262
  * Compiles the query to SQL for a specific dialect
6913
7263
  * @param dialect - Database dialect to compile for
6914
7264
  * @returns Compiled query with SQL and parameters
7265
+ * @example
7266
+ * const compiled = qb.select('id', 'name')
7267
+ * .where(eq(userTable.columns.active, true))
7268
+ * .compile('postgres');
7269
+ * console.log(compiled.sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
6915
7270
  */
6916
7271
  compile(dialect) {
6917
7272
  const resolved = resolveDialectInput(dialect);
@@ -6921,6 +7276,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6921
7276
  * Converts the query to SQL string for a specific dialect
6922
7277
  * @param dialect - Database dialect to generate SQL for
6923
7278
  * @returns SQL string representation of the query
7279
+ * @example
7280
+ * const sql = qb.select('id', 'name')
7281
+ * .where(eq(userTable.columns.active, true))
7282
+ * .toSql('postgres');
7283
+ * console.log(sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
6924
7284
  */
6925
7285
  toSql(dialect) {
6926
7286
  return this.compile(dialect).sql;
@@ -6928,6 +7288,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6928
7288
  /**
6929
7289
  * Gets the hydration plan for the query
6930
7290
  * @returns Hydration plan or undefined if none exists
7291
+ * @example
7292
+ * const plan = qb.include('posts').getHydrationPlan();
7293
+ * console.log(plan?.relations); // Information about included relations
6931
7294
  */
6932
7295
  getHydrationPlan() {
6933
7296
  return this.context.hydration.getPlan();
@@ -6935,6 +7298,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6935
7298
  /**
6936
7299
  * Gets the Abstract Syntax Tree (AST) representation of the query
6937
7300
  * @returns Query AST with hydration applied
7301
+ * @example
7302
+ * const ast = qb.select('id', 'name').getAST();
7303
+ * console.log(ast.columns); // Array of column nodes
7304
+ * console.log(ast.from); // From clause information
6938
7305
  */
6939
7306
  getAST() {
6940
7307
  return this.context.hydration.applyToAst(this.context.state.ast);
@@ -6965,61 +7332,6 @@ var isTableDef = (value) => {
6965
7332
  return true;
6966
7333
  };
6967
7334
 
6968
- // src/orm/entity-metadata.ts
6969
- var metadataMap = /* @__PURE__ */ new Map();
6970
- var ensureEntityMetadata = (target) => {
6971
- let meta = metadataMap.get(target);
6972
- if (!meta) {
6973
- meta = {
6974
- target,
6975
- tableName: target.name || "unknown",
6976
- columns: {},
6977
- relations: {}
6978
- };
6979
- metadataMap.set(target, meta);
6980
- }
6981
- return meta;
6982
- };
6983
- var getEntityMetadata = (target) => {
6984
- return metadataMap.get(target);
6985
- };
6986
- var getAllEntityMetadata = () => {
6987
- return Array.from(metadataMap.values());
6988
- };
6989
- var addColumnMetadata = (target, propertyKey, column) => {
6990
- const meta = ensureEntityMetadata(target);
6991
- meta.columns[propertyKey] = { ...column };
6992
- };
6993
- var addRelationMetadata = (target, propertyKey, relation) => {
6994
- const meta = ensureEntityMetadata(target);
6995
- meta.relations[propertyKey] = relation;
6996
- };
6997
- var setEntityTableName = (target, tableName, hooks) => {
6998
- const meta = ensureEntityMetadata(target);
6999
- if (tableName && tableName.length > 0) {
7000
- meta.tableName = tableName;
7001
- }
7002
- if (hooks) {
7003
- meta.hooks = hooks;
7004
- }
7005
- };
7006
- var buildTableDef = (meta) => {
7007
- if (meta.table) {
7008
- return meta.table;
7009
- }
7010
- const columns = {};
7011
- for (const [key, def] of Object.entries(meta.columns)) {
7012
- columns[key] = {
7013
- ...def,
7014
- name: key,
7015
- table: meta.tableName
7016
- };
7017
- }
7018
- const table = defineTable(meta.tableName, columns, {}, meta.hooks);
7019
- meta.table = table;
7020
- return table;
7021
- };
7022
-
7023
7335
  // src/decorators/bootstrap.ts
7024
7336
  var unwrapTarget = (target) => {
7025
7337
  if (typeof target === "function" && target.prototype === void 0) {
@@ -7139,7 +7451,15 @@ var selectFromEntity = (ctor) => {
7139
7451
  if (!table) {
7140
7452
  throw new Error(`Entity '${ctor.name}' is not registered with decorators or has not been bootstrapped`);
7141
7453
  }
7142
- return new SelectQueryBuilder(table);
7454
+ return new SelectQueryBuilder(
7455
+ table,
7456
+ void 0,
7457
+ void 0,
7458
+ void 0,
7459
+ void 0,
7460
+ void 0,
7461
+ ctor
7462
+ );
7143
7463
  };
7144
7464
  var entityRef = (ctor) => {
7145
7465
  const table = getTableDefFromEntity(ctor);
@@ -7821,6 +8141,39 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
7821
8141
  };
7822
8142
  var isTableSourceNode2 = (source) => typeof source.type === "string";
7823
8143
 
8144
+ // src/query/target.ts
8145
+ var resolveEntityTarget = (ctor) => {
8146
+ const table = getTableDefFromEntity(ctor);
8147
+ if (!table) {
8148
+ throw new Error(`Entity '${ctor.name}' is not registered with decorators`);
8149
+ }
8150
+ return table;
8151
+ };
8152
+ var resolveTable = (target) => {
8153
+ if (isTableDef(target)) {
8154
+ return target;
8155
+ }
8156
+ return resolveEntityTarget(target);
8157
+ };
8158
+
8159
+ // src/query/index.ts
8160
+ var selectFrom = (target) => {
8161
+ const table = resolveTable(target);
8162
+ return new SelectQueryBuilder(table);
8163
+ };
8164
+ var insertInto = (target) => {
8165
+ const table = resolveTable(target);
8166
+ return new InsertQueryBuilder(table);
8167
+ };
8168
+ var update = (target) => {
8169
+ const table = resolveTable(target);
8170
+ return new UpdateQueryBuilder(table);
8171
+ };
8172
+ var deleteFrom = (target) => {
8173
+ const table = resolveTable(target);
8174
+ return new DeleteQueryBuilder(table);
8175
+ };
8176
+
7824
8177
  // src/core/ddl/sql-writing.ts
7825
8178
  var resolvePrimaryKey = (table) => {
7826
8179
  if (Array.isArray(table.primaryKey) && table.primaryKey.length > 0) {
@@ -12351,7 +12704,9 @@ export {
12351
12704
  BelongsTo,
12352
12705
  BelongsToMany,
12353
12706
  Column,
12707
+ ConstructorMaterializationStrategy,
12354
12708
  DefaultBelongsToReference,
12709
+ DefaultEntityMaterializer,
12355
12710
  DefaultHasManyCollection,
12356
12711
  DefaultManyToManyCollection,
12357
12712
  DeleteQueryBuilder,
@@ -12367,6 +12722,7 @@ export {
12367
12722
  Pool,
12368
12723
  PostgresDialect,
12369
12724
  PrimaryKey,
12725
+ PrototypeMaterializationStrategy,
12370
12726
  RelationKinds,
12371
12727
  STANDARD_COLUMN_TYPES,
12372
12728
  SelectQueryBuilder,
@@ -12438,6 +12794,7 @@ export {
12438
12794
  dayOfWeek,
12439
12795
  defineTable,
12440
12796
  degrees,
12797
+ deleteFrom,
12441
12798
  denseRank,
12442
12799
  diffSchema,
12443
12800
  div,
@@ -12474,6 +12831,7 @@ export {
12474
12831
  inList,
12475
12832
  inSubquery,
12476
12833
  initcap,
12834
+ insertInto,
12477
12835
  instr,
12478
12836
  introspectSchema,
12479
12837
  isCaseExpressionNode,
@@ -12516,6 +12874,7 @@ export {
12516
12874
  lt,
12517
12875
  lte,
12518
12876
  ltrim,
12877
+ materializeAs,
12519
12878
  max,
12520
12879
  md5,
12521
12880
  min,
@@ -12562,6 +12921,7 @@ export {
12562
12921
  rtrim,
12563
12922
  second,
12564
12923
  sel,
12924
+ selectFrom,
12565
12925
  selectFromEntity,
12566
12926
  setRelations,
12567
12927
  sha1,
@@ -12585,6 +12945,7 @@ export {
12585
12945
  trunc,
12586
12946
  truncate,
12587
12947
  unixTimestamp,
12948
+ update,
12588
12949
  upper,
12589
12950
  utcNow,
12590
12951
  valueToOperand,