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.cjs CHANGED
@@ -47,7 +47,9 @@ __export(index_exports, {
47
47
  BelongsTo: () => BelongsTo,
48
48
  BelongsToMany: () => BelongsToMany,
49
49
  Column: () => Column,
50
+ ConstructorMaterializationStrategy: () => ConstructorMaterializationStrategy,
50
51
  DefaultBelongsToReference: () => DefaultBelongsToReference,
52
+ DefaultEntityMaterializer: () => DefaultEntityMaterializer,
51
53
  DefaultHasManyCollection: () => DefaultHasManyCollection,
52
54
  DefaultManyToManyCollection: () => DefaultManyToManyCollection,
53
55
  DeleteQueryBuilder: () => DeleteQueryBuilder,
@@ -63,6 +65,7 @@ __export(index_exports, {
63
65
  Pool: () => Pool,
64
66
  PostgresDialect: () => PostgresDialect,
65
67
  PrimaryKey: () => PrimaryKey,
68
+ PrototypeMaterializationStrategy: () => PrototypeMaterializationStrategy,
66
69
  RelationKinds: () => RelationKinds,
67
70
  STANDARD_COLUMN_TYPES: () => STANDARD_COLUMN_TYPES,
68
71
  SelectQueryBuilder: () => SelectQueryBuilder,
@@ -134,6 +137,7 @@ __export(index_exports, {
134
137
  dayOfWeek: () => dayOfWeek,
135
138
  defineTable: () => defineTable,
136
139
  degrees: () => degrees,
140
+ deleteFrom: () => deleteFrom,
137
141
  denseRank: () => denseRank,
138
142
  diffSchema: () => diffSchema,
139
143
  div: () => div,
@@ -170,6 +174,7 @@ __export(index_exports, {
170
174
  inList: () => inList,
171
175
  inSubquery: () => inSubquery,
172
176
  initcap: () => initcap,
177
+ insertInto: () => insertInto,
173
178
  instr: () => instr,
174
179
  introspectSchema: () => introspectSchema,
175
180
  isCaseExpressionNode: () => isCaseExpressionNode,
@@ -212,6 +217,7 @@ __export(index_exports, {
212
217
  lt: () => lt,
213
218
  lte: () => lte,
214
219
  ltrim: () => ltrim,
220
+ materializeAs: () => materializeAs,
215
221
  max: () => max,
216
222
  md5: () => md5,
217
223
  min: () => min,
@@ -258,6 +264,7 @@ __export(index_exports, {
258
264
  rtrim: () => rtrim,
259
265
  second: () => second,
260
266
  sel: () => sel,
267
+ selectFrom: () => selectFrom,
261
268
  selectFromEntity: () => selectFromEntity,
262
269
  setRelations: () => setRelations,
263
270
  sha1: () => sha1,
@@ -281,6 +288,7 @@ __export(index_exports, {
281
288
  trunc: () => trunc,
282
289
  truncate: () => truncate,
283
290
  unixTimestamp: () => unixTimestamp,
291
+ update: () => update,
284
292
  upper: () => upper,
285
293
  utcNow: () => utcNow,
286
294
  valueToOperand: () => valueToOperand,
@@ -6234,6 +6242,132 @@ var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOp
6234
6242
  }
6235
6243
  };
6236
6244
 
6245
+ // src/orm/entity-metadata.ts
6246
+ var metadataMap = /* @__PURE__ */ new Map();
6247
+ var ensureEntityMetadata = (target) => {
6248
+ let meta = metadataMap.get(target);
6249
+ if (!meta) {
6250
+ meta = {
6251
+ target,
6252
+ tableName: target.name || "unknown",
6253
+ columns: {},
6254
+ relations: {}
6255
+ };
6256
+ metadataMap.set(target, meta);
6257
+ }
6258
+ return meta;
6259
+ };
6260
+ var getEntityMetadata = (target) => {
6261
+ return metadataMap.get(target);
6262
+ };
6263
+ var getAllEntityMetadata = () => {
6264
+ return Array.from(metadataMap.values());
6265
+ };
6266
+ var addColumnMetadata = (target, propertyKey, column) => {
6267
+ const meta = ensureEntityMetadata(target);
6268
+ meta.columns[propertyKey] = { ...column };
6269
+ };
6270
+ var addRelationMetadata = (target, propertyKey, relation) => {
6271
+ const meta = ensureEntityMetadata(target);
6272
+ meta.relations[propertyKey] = relation;
6273
+ };
6274
+ var setEntityTableName = (target, tableName, hooks) => {
6275
+ const meta = ensureEntityMetadata(target);
6276
+ if (tableName && tableName.length > 0) {
6277
+ meta.tableName = tableName;
6278
+ }
6279
+ if (hooks) {
6280
+ meta.hooks = hooks;
6281
+ }
6282
+ };
6283
+ var buildTableDef = (meta) => {
6284
+ if (meta.table) {
6285
+ return meta.table;
6286
+ }
6287
+ const columns = {};
6288
+ for (const [key, def] of Object.entries(meta.columns)) {
6289
+ columns[key] = {
6290
+ ...def,
6291
+ name: key,
6292
+ table: meta.tableName
6293
+ };
6294
+ }
6295
+ const table = defineTable(meta.tableName, columns, {}, meta.hooks);
6296
+ meta.table = table;
6297
+ return table;
6298
+ };
6299
+
6300
+ // src/orm/entity-registry.ts
6301
+ var tableToConstructor = /* @__PURE__ */ new Map();
6302
+ var rebuildRegistry = () => {
6303
+ tableToConstructor.clear();
6304
+ for (const meta of getAllEntityMetadata()) {
6305
+ if (meta.table) {
6306
+ tableToConstructor.set(meta.table, meta.target);
6307
+ }
6308
+ }
6309
+ };
6310
+
6311
+ // src/orm/entity-materializer.ts
6312
+ var PrototypeMaterializationStrategy = class {
6313
+ materialize(ctor, data) {
6314
+ const instance = Object.create(ctor.prototype);
6315
+ Object.assign(instance, data);
6316
+ return instance;
6317
+ }
6318
+ };
6319
+ var ConstructorMaterializationStrategy = class {
6320
+ materialize(ctor, data) {
6321
+ const instance = Reflect.construct(ctor, []);
6322
+ Object.assign(instance, data);
6323
+ return instance;
6324
+ }
6325
+ };
6326
+ var DefaultEntityMaterializer = class {
6327
+ constructor(strategy = new ConstructorMaterializationStrategy()) {
6328
+ this.strategy = strategy;
6329
+ }
6330
+ materialize(ctor, row) {
6331
+ const instance = this.strategy.materialize(ctor, row);
6332
+ this.materializeRelations(instance, ctor);
6333
+ return instance;
6334
+ }
6335
+ materializeMany(ctor, rows) {
6336
+ return rows.map((row) => this.materialize(ctor, row));
6337
+ }
6338
+ /**
6339
+ * Recursively materializes nested relation data.
6340
+ */
6341
+ materializeRelations(instance, _ctor) {
6342
+ rebuildRegistry();
6343
+ for (const [key, value] of Object.entries(instance)) {
6344
+ if (value === null || value === void 0) continue;
6345
+ if (typeof value === "object" && !Array.isArray(value)) {
6346
+ const nested = value;
6347
+ if (this.isEntityLike(nested)) {
6348
+ }
6349
+ }
6350
+ if (Array.isArray(value) && value.length > 0) {
6351
+ const first = value[0];
6352
+ if (typeof first === "object" && first !== null && this.isEntityLike(first)) {
6353
+ }
6354
+ }
6355
+ }
6356
+ }
6357
+ /**
6358
+ * Simple heuristic to check if an object looks like an entity.
6359
+ */
6360
+ isEntityLike(obj) {
6361
+ return "id" in obj || Object.keys(obj).some(
6362
+ (k) => k.endsWith("Id") || k === "createdAt" || k === "updatedAt"
6363
+ );
6364
+ }
6365
+ };
6366
+ var materializeAs = (ctor, results) => {
6367
+ const materializer = new DefaultEntityMaterializer();
6368
+ return materializer.materializeMany(ctor, results);
6369
+ };
6370
+
6237
6371
  // src/query-builder/query-resolution.ts
6238
6372
  function resolveSelectQuery(query) {
6239
6373
  const candidate = query;
@@ -6644,6 +6778,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6644
6778
  relationFacet;
6645
6779
  lazyRelations;
6646
6780
  lazyRelationOptions;
6781
+ entityConstructor;
6647
6782
  /**
6648
6783
  * Creates a new SelectQueryBuilder instance
6649
6784
  * @param table - Table definition to query
@@ -6651,7 +6786,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6651
6786
  * @param hydration - Optional hydration manager
6652
6787
  * @param dependencies - Optional query builder dependencies
6653
6788
  */
6654
- constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions) {
6789
+ constructor(table, state, hydration, dependencies, lazyRelations, lazyRelationOptions, entityConstructor) {
6655
6790
  const deps = resolveSelectQueryBuilderDependencies(dependencies);
6656
6791
  this.env = { table, deps };
6657
6792
  const createAstService = (nextState) => deps.createQueryAstService(table, nextState);
@@ -6663,6 +6798,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6663
6798
  };
6664
6799
  this.lazyRelations = new Set(lazyRelations ?? []);
6665
6800
  this.lazyRelationOptions = new Map(lazyRelationOptions ?? []);
6801
+ this.entityConstructor = entityConstructor;
6666
6802
  this.columnSelector = deps.createColumnSelector(this.env);
6667
6803
  const relationManager = deps.createRelationManager(this.env);
6668
6804
  this.fromFacet = new SelectFromFacet(this.env, createAstService);
@@ -6686,12 +6822,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6686
6822
  context.hydration,
6687
6823
  this.env.deps,
6688
6824
  lazyRelations,
6689
- lazyRelationOptions
6825
+ lazyRelationOptions,
6826
+ this.entityConstructor
6690
6827
  );
6691
6828
  }
6692
6829
  /**
6693
6830
  * Applies an alias to the root FROM table.
6694
6831
  * @param alias - Alias to apply
6832
+ * @example
6833
+ * const qb = new SelectQueryBuilder(userTable).as('u');
6695
6834
  */
6696
6835
  as(alias) {
6697
6836
  const nextContext = this.fromFacet.as(this.context, alias);
@@ -6749,6 +6888,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6749
6888
  * Selects raw column expressions
6750
6889
  * @param cols - Column expressions as strings
6751
6890
  * @returns New query builder instance with raw column selections
6891
+ * @example
6892
+ * qb.selectRaw('COUNT(*) as total', 'UPPER(name) as upper_name');
6752
6893
  */
6753
6894
  selectRaw(...cols) {
6754
6895
  return this.clone(this.projectionFacet.selectRaw(this.context, cols));
@@ -6759,6 +6900,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6759
6900
  * @param query - Query builder or query node for the CTE
6760
6901
  * @param columns - Optional column names for the CTE
6761
6902
  * @returns New query builder instance with the CTE
6903
+ * @example
6904
+ * const recentUsers = new SelectQueryBuilder(userTable)
6905
+ * .where(gt(userTable.columns.createdAt, subDays(now(), 30)));
6906
+ * const qb = new SelectQueryBuilder(userTable)
6907
+ * .with('recent_users', recentUsers)
6908
+ * .from('recent_users');
6762
6909
  */
6763
6910
  with(name, query, columns) {
6764
6911
  const subAst = resolveSelectQuery(query);
@@ -6771,6 +6918,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6771
6918
  * @param query - Query builder or query node for the CTE
6772
6919
  * @param columns - Optional column names for the CTE
6773
6920
  * @returns New query builder instance with the recursive CTE
6921
+ * @example
6922
+ * // Base case: select root nodes
6923
+ * const baseQuery = new SelectQueryBuilder(orgTable)
6924
+ * .where(eq(orgTable.columns.parentId, 1));
6925
+ * // Recursive case: join with the CTE itself
6926
+ * const recursiveQuery = new SelectQueryBuilder(orgTable)
6927
+ * .join('org_hierarchy', 'oh', eq(orgTable.columns.parentId, col('oh.id')));
6928
+ * // Combine base and recursive parts
6929
+ * const orgHierarchy = baseQuery.union(recursiveQuery);
6930
+ * // Use in main query
6931
+ * const qb = new SelectQueryBuilder(orgTable)
6932
+ * .withRecursive('org_hierarchy', orgHierarchy)
6933
+ * .from('org_hierarchy');
6774
6934
  */
6775
6935
  withRecursive(name, query, columns) {
6776
6936
  const subAst = resolveSelectQuery(query);
@@ -6783,6 +6943,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6783
6943
  * @param alias - Alias for the derived table
6784
6944
  * @param columnAliases - Optional column alias list
6785
6945
  * @returns New query builder instance with updated FROM
6946
+ * @example
6947
+ * const subquery = new SelectQueryBuilder(userTable)
6948
+ * .select('id', 'name')
6949
+ * .where(gt(userTable.columns.score, 100));
6950
+ * qb.fromSubquery(subquery, 'high_scorers', ['userId', 'userName']);
6786
6951
  */
6787
6952
  fromSubquery(subquery, alias, columnAliases) {
6788
6953
  const subAst = resolveSelectQuery(subquery);
@@ -6795,6 +6960,13 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6795
6960
  * @param args - Optional function arguments
6796
6961
  * @param alias - Optional alias for the function table
6797
6962
  * @param options - Optional function-table metadata (lateral, ordinality, column aliases, schema)
6963
+ * @example
6964
+ * qb.fromFunctionTable(
6965
+ * 'generate_series',
6966
+ * [literal(1), literal(10), literal(1)],
6967
+ * 'series',
6968
+ * { columnAliases: ['value'] }
6969
+ * );
6798
6970
  */
6799
6971
  fromFunctionTable(name, args = [], alias, options) {
6800
6972
  const nextContext = this.fromFacet.fromFunctionTable(this.context, name, args, alias, options);
@@ -6805,6 +6977,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6805
6977
  * @param alias - Alias for the subquery column
6806
6978
  * @param sub - Query builder or query node for the subquery
6807
6979
  * @returns New query builder instance with the subquery selection
6980
+ * @example
6981
+ * const postCount = new SelectQueryBuilder(postTable)
6982
+ * .select(count(postTable.columns.id))
6983
+ * .where(eq(postTable.columns.userId, col('u.id')));
6984
+ * qb.select('id', 'name')
6985
+ * .selectSubquery('postCount', postCount);
6808
6986
  */
6809
6987
  selectSubquery(alias, sub2) {
6810
6988
  const query = resolveSelectQuery(sub2);
@@ -6818,6 +6996,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6818
6996
  * @param joinKind - Join kind (defaults to INNER)
6819
6997
  * @param columnAliases - Optional column alias list for the derived table
6820
6998
  * @returns New query builder instance with the derived-table join
6999
+ * @example
7000
+ * const activeUsers = new SelectQueryBuilder(userTable)
7001
+ * .where(eq(userTable.columns.active, true));
7002
+ * qb.joinSubquery(
7003
+ * activeUsers,
7004
+ * 'au',
7005
+ * eq(col('t.userId'), col('au.id')),
7006
+ * JOIN_KINDS.LEFT
7007
+ * );
6821
7008
  */
6822
7009
  joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
6823
7010
  const subAst = resolveSelectQuery(subquery);
@@ -6832,6 +7019,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6832
7019
  * @param condition - Join condition expression
6833
7020
  * @param joinKind - Kind of join (defaults to INNER)
6834
7021
  * @param options - Optional metadata (lateral, ordinality, column aliases, schema)
7022
+ * @example
7023
+ * qb.joinFunctionTable(
7024
+ * 'generate_series',
7025
+ * [literal(1), literal(10)],
7026
+ * 'gs',
7027
+ * eq(col('t.value'), col('gs.value')),
7028
+ * JOIN_KINDS.INNER,
7029
+ * { columnAliases: ['value'] }
7030
+ * );
6835
7031
  */
6836
7032
  joinFunctionTable(name, args = [], alias, condition, joinKind = JOIN_KINDS.INNER, options) {
6837
7033
  const nextContext = this.joinFacet.joinFunctionTable(this.context, name, args, alias, condition, joinKind, options);
@@ -6842,6 +7038,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6842
7038
  * @param table - Table to join
6843
7039
  * @param condition - Join condition expression
6844
7040
  * @returns New query builder instance with the INNER JOIN
7041
+ * @example
7042
+ * qb.innerJoin(
7043
+ * postTable,
7044
+ * eq(userTable.columns.id, postTable.columns.userId)
7045
+ * );
6845
7046
  */
6846
7047
  innerJoin(table, condition) {
6847
7048
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
@@ -6852,6 +7053,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6852
7053
  * @param table - Table to join
6853
7054
  * @param condition - Join condition expression
6854
7055
  * @returns New query builder instance with the LEFT JOIN
7056
+ * @example
7057
+ * qb.leftJoin(
7058
+ * postTable,
7059
+ * eq(userTable.columns.id, postTable.columns.userId)
7060
+ * );
6855
7061
  */
6856
7062
  leftJoin(table, condition) {
6857
7063
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
@@ -6862,6 +7068,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6862
7068
  * @param table - Table to join
6863
7069
  * @param condition - Join condition expression
6864
7070
  * @returns New query builder instance with the RIGHT JOIN
7071
+ * @example
7072
+ * qb.rightJoin(
7073
+ * postTable,
7074
+ * eq(userTable.columns.id, postTable.columns.userId)
7075
+ * );
6865
7076
  */
6866
7077
  rightJoin(table, condition) {
6867
7078
  const nextContext = this.joinFacet.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
@@ -6872,6 +7083,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6872
7083
  * @param relationName - Name of the relationship to match
6873
7084
  * @param predicate - Optional predicate expression
6874
7085
  * @returns New query builder instance with the relationship match
7086
+ * @example
7087
+ * qb.match('posts', eq(postTable.columns.published, true));
6875
7088
  */
6876
7089
  match(relationName, predicate) {
6877
7090
  const nextContext = this.relationFacet.match(this.context, relationName, predicate);
@@ -6883,6 +7096,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6883
7096
  * @param joinKind - Type of join (defaults to INNER)
6884
7097
  * @param extraCondition - Optional additional join condition
6885
7098
  * @returns New query builder instance with the relationship join
7099
+ * @example
7100
+ * qb.joinRelation('posts', JOIN_KINDS.LEFT);
7101
+ * @example
7102
+ * qb.joinRelation('posts', JOIN_KINDS.INNER, eq(postTable.columns.published, true));
6886
7103
  */
6887
7104
  joinRelation(relationName, joinKind = JOIN_KINDS.INNER, extraCondition) {
6888
7105
  const nextContext = this.relationFacet.joinRelation(this.context, relationName, joinKind, extraCondition);
@@ -6893,6 +7110,15 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6893
7110
  * @param relationName - Name of the relationship to include
6894
7111
  * @param options - Optional include options
6895
7112
  * @returns New query builder instance with the relationship inclusion
7113
+ * @example
7114
+ * qb.include('posts');
7115
+ * @example
7116
+ * qb.include('posts', { columns: ['id', 'title', 'published'] });
7117
+ * @example
7118
+ * qb.include('posts', {
7119
+ * columns: ['id', 'title'],
7120
+ * where: eq(postTable.columns.published, true)
7121
+ * });
6896
7122
  */
6897
7123
  include(relationName, options) {
6898
7124
  const nextContext = this.relationFacet.include(this.context, relationName, options);
@@ -6903,6 +7129,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6903
7129
  * @param relationName - Name of the relation to include lazily
6904
7130
  * @param options - Optional include options for lazy loading
6905
7131
  * @returns New query builder instance with lazy relation inclusion
7132
+ * @example
7133
+ * const qb = new SelectQueryBuilder(userTable).includeLazy('posts');
7134
+ * const users = await qb.execute(session);
7135
+ * // Access posts later - they will be loaded on demand
7136
+ * const posts = await users[0].posts;
6906
7137
  */
6907
7138
  includeLazy(relationName, options) {
6908
7139
  let nextContext = this.context;
@@ -6932,6 +7163,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6932
7163
  }
6933
7164
  /**
6934
7165
  * Convenience alias for including only specific columns from a relation.
7166
+ * @example
7167
+ * qb.includePick('posts', ['id', 'title', 'createdAt']);
6935
7168
  */
6936
7169
  includePick(relationName, cols) {
6937
7170
  const options = { columns: cols };
@@ -6941,6 +7174,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6941
7174
  * Selects columns for the root table and relations from an array of entries
6942
7175
  * @param config - Configuration array for deep column selection
6943
7176
  * @returns New query builder instance with deep column selections
7177
+ * @example
7178
+ * qb.selectColumnsDeep([
7179
+ * { type: 'root', columns: ['id', 'name'] },
7180
+ * { type: 'relation', relationName: 'posts', columns: ['id', 'title'] }
7181
+ * ]);
6944
7182
  */
6945
7183
  selectColumnsDeep(config) {
6946
7184
  let currBuilder = this;
@@ -6976,12 +7214,67 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6976
7214
  return this.env.table;
6977
7215
  }
6978
7216
  /**
6979
- * Executes the query and returns hydrated results
7217
+ * Ensures that if no columns are selected, all columns from the table are selected by default.
7218
+ */
7219
+ ensureDefaultSelection() {
7220
+ const columns = this.context.state.ast.columns;
7221
+ if (!columns || columns.length === 0) {
7222
+ return this.select(...Object.keys(this.env.table.columns));
7223
+ }
7224
+ return this;
7225
+ }
7226
+ /**
7227
+ * Executes the query and returns hydrated results.
7228
+ * If the builder was created with an entity constructor (e.g. via selectFromEntity),
7229
+ * this will automatically return fully materialized entity instances.
7230
+ *
6980
7231
  * @param ctx - ORM session context
6981
- * @returns Promise of entity instances
7232
+ * @returns Promise of entity instances (or objects if generic T is not an entity)
7233
+ * @example
7234
+ * const users = await selectFromEntity(User).execute(session);
7235
+ * // users is User[]
7236
+ * users[0] instanceof User; // true
6982
7237
  */
6983
7238
  async execute(ctx) {
6984
- return executeHydrated(ctx, this);
7239
+ if (this.entityConstructor) {
7240
+ return this.executeAs(this.entityConstructor, ctx);
7241
+ }
7242
+ const builder = this.ensureDefaultSelection();
7243
+ return executeHydrated(ctx, builder);
7244
+ }
7245
+ /**
7246
+ * Executes the query and returns plain row objects (POJOs), ignoring any entity materialization.
7247
+ * Use this if you want raw data even when using selectFromEntity.
7248
+ *
7249
+ * @param ctx - ORM session context
7250
+ * @returns Promise of plain entity instances
7251
+ * @example
7252
+ * const rows = await selectFromEntity(User).executePlain(session);
7253
+ * // rows is EntityInstance<UserTable>[] (plain objects)
7254
+ * rows[0] instanceof User; // false
7255
+ */
7256
+ async executePlain(ctx) {
7257
+ const builder = this.ensureDefaultSelection();
7258
+ return executeHydrated(ctx, builder);
7259
+ }
7260
+ /**
7261
+ * Executes the query and returns results as real class instances.
7262
+ * Unlike execute(), this returns actual instances of the decorated entity class
7263
+ * with working methods and proper instanceof checks.
7264
+ * @param entityClass - The entity class constructor
7265
+ * @param ctx - ORM session context
7266
+ * @returns Promise of entity class instances
7267
+ * @example
7268
+ * const users = await selectFromEntity(User)
7269
+ * .include('posts')
7270
+ * .executeAs(User, session);
7271
+ * users[0] instanceof User; // true!
7272
+ * users[0].getFullName(); // works!
7273
+ */
7274
+ async executeAs(entityClass, ctx) {
7275
+ const builder = this.ensureDefaultSelection();
7276
+ const results = await executeHydrated(ctx, builder);
7277
+ return materializeAs(entityClass, results);
6985
7278
  }
6986
7279
  /**
6987
7280
  * Executes a count query for the current builder without LIMIT/OFFSET clauses.
@@ -6999,21 +7292,38 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
6999
7292
  * const { items, totalItems } = await qb.executePaged(session, { page: 1, pageSize: 20 });
7000
7293
  */
7001
7294
  async executePaged(session, options) {
7002
- return executePagedQuery(this, session, options, (sess) => this.count(sess));
7295
+ const builder = this.ensureDefaultSelection();
7296
+ return executePagedQuery(builder, session, options, (sess) => this.count(sess));
7003
7297
  }
7004
7298
  /**
7005
7299
  * Executes the query with provided execution and hydration contexts
7006
7300
  * @param execCtx - Execution context
7007
7301
  * @param hydCtx - Hydration context
7008
7302
  * @returns Promise of entity instances
7303
+ * @example
7304
+ * const execCtx = new ExecutionContext(session);
7305
+ * const hydCtx = new HydrationContext();
7306
+ * const users = await qb.executeWithContexts(execCtx, hydCtx);
7009
7307
  */
7010
7308
  async executeWithContexts(execCtx, hydCtx) {
7011
- return executeHydratedWithContexts(execCtx, hydCtx, this);
7309
+ const builder = this.ensureDefaultSelection();
7310
+ const results = await executeHydratedWithContexts(execCtx, hydCtx, builder);
7311
+ if (this.entityConstructor) {
7312
+ return materializeAs(this.entityConstructor, results);
7313
+ }
7314
+ return results;
7012
7315
  }
7013
7316
  /**
7014
7317
  * Adds a WHERE condition to the query
7015
7318
  * @param expr - Expression for the WHERE clause
7016
7319
  * @returns New query builder instance with the WHERE condition
7320
+ * @example
7321
+ * qb.where(eq(userTable.columns.id, 1));
7322
+ * @example
7323
+ * qb.where(and(
7324
+ * eq(userTable.columns.active, true),
7325
+ * gt(userTable.columns.createdAt, subDays(now(), 30))
7326
+ * ));
7017
7327
  */
7018
7328
  where(expr) {
7019
7329
  const nextContext = this.predicateFacet.where(this.context, expr);
@@ -7023,6 +7333,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7023
7333
  * Adds a GROUP BY clause to the query
7024
7334
  * @param term - Column definition or ordering term to group by
7025
7335
  * @returns New query builder instance with the GROUP BY clause
7336
+ * @example
7337
+ * qb.select('departmentId', count(userTable.columns.id))
7338
+ * .groupBy(userTable.columns.departmentId);
7026
7339
  */
7027
7340
  groupBy(term) {
7028
7341
  const nextContext = this.predicateFacet.groupBy(this.context, term);
@@ -7032,6 +7345,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7032
7345
  * Adds a HAVING condition to the query
7033
7346
  * @param expr - Expression for the HAVING clause
7034
7347
  * @returns New query builder instance with the HAVING condition
7348
+ * @example
7349
+ * qb.select('departmentId', count(userTable.columns.id))
7350
+ * .groupBy(userTable.columns.departmentId)
7351
+ * .having(gt(count(userTable.columns.id), 5));
7035
7352
  */
7036
7353
  having(expr) {
7037
7354
  const nextContext = this.predicateFacet.having(this.context, expr);
@@ -7054,6 +7371,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7054
7371
  * Adds a DISTINCT clause to the query
7055
7372
  * @param cols - Columns to make distinct
7056
7373
  * @returns New query builder instance with the DISTINCT clause
7374
+ * @example
7375
+ * qb.distinct(userTable.columns.email);
7376
+ * @example
7377
+ * qb.distinct(userTable.columns.firstName, userTable.columns.lastName);
7057
7378
  */
7058
7379
  distinct(...cols) {
7059
7380
  return this.clone(this.projectionFacet.distinct(this.context, cols));
@@ -7062,6 +7383,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7062
7383
  * Adds a LIMIT clause to the query
7063
7384
  * @param n - Maximum number of rows to return
7064
7385
  * @returns New query builder instance with the LIMIT clause
7386
+ * @example
7387
+ * qb.limit(10);
7388
+ * @example
7389
+ * qb.limit(20).offset(40); // Pagination: page 3 with 20 items per page
7065
7390
  */
7066
7391
  limit(n) {
7067
7392
  const nextContext = this.predicateFacet.limit(this.context, n);
@@ -7071,6 +7396,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7071
7396
  * Adds an OFFSET clause to the query
7072
7397
  * @param n - Number of rows to skip
7073
7398
  * @returns New query builder instance with the OFFSET clause
7399
+ * @example
7400
+ * qb.offset(10);
7401
+ * @example
7402
+ * qb.limit(20).offset(40); // Pagination: page 3 with 20 items per page
7074
7403
  */
7075
7404
  offset(n) {
7076
7405
  const nextContext = this.predicateFacet.offset(this.context, n);
@@ -7080,6 +7409,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7080
7409
  * Combines this query with another using UNION
7081
7410
  * @param query - Query to union with
7082
7411
  * @returns New query builder instance with the set operation
7412
+ * @example
7413
+ * const activeUsers = new SelectQueryBuilder(userTable)
7414
+ * .where(eq(userTable.columns.active, true));
7415
+ * const inactiveUsers = new SelectQueryBuilder(userTable)
7416
+ * .where(eq(userTable.columns.active, false));
7417
+ * qb.union(activeUsers).union(inactiveUsers);
7083
7418
  */
7084
7419
  union(query) {
7085
7420
  return this.clone(this.applySetOperation("UNION", query));
@@ -7088,6 +7423,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7088
7423
  * Combines this query with another using UNION ALL
7089
7424
  * @param query - Query to union with
7090
7425
  * @returns New query builder instance with the set operation
7426
+ * @example
7427
+ * const q1 = new SelectQueryBuilder(userTable).where(gt(userTable.columns.score, 80));
7428
+ * const q2 = new SelectQueryBuilder(userTable).where(lt(userTable.columns.score, 20));
7429
+ * qb.unionAll(q1).unionAll(q2);
7091
7430
  */
7092
7431
  unionAll(query) {
7093
7432
  return this.clone(this.applySetOperation("UNION ALL", query));
@@ -7096,6 +7435,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7096
7435
  * Combines this query with another using INTERSECT
7097
7436
  * @param query - Query to intersect with
7098
7437
  * @returns New query builder instance with the set operation
7438
+ * @example
7439
+ * const activeUsers = new SelectQueryBuilder(userTable)
7440
+ * .where(eq(userTable.columns.active, true));
7441
+ * const premiumUsers = new SelectQueryBuilder(userTable)
7442
+ * .where(eq(userTable.columns.premium, true));
7443
+ * qb.intersect(activeUsers).intersect(premiumUsers);
7099
7444
  */
7100
7445
  intersect(query) {
7101
7446
  return this.clone(this.applySetOperation("INTERSECT", query));
@@ -7104,6 +7449,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7104
7449
  * Combines this query with another using EXCEPT
7105
7450
  * @param query - Query to subtract
7106
7451
  * @returns New query builder instance with the set operation
7452
+ * @example
7453
+ * const allUsers = new SelectQueryBuilder(userTable);
7454
+ * const inactiveUsers = new SelectQueryBuilder(userTable)
7455
+ * .where(eq(userTable.columns.active, false));
7456
+ * qb.except(allUsers).except(inactiveUsers); // Only active users
7107
7457
  */
7108
7458
  except(query) {
7109
7459
  return this.clone(this.applySetOperation("EXCEPT", query));
@@ -7112,6 +7462,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7112
7462
  * Adds a WHERE EXISTS condition to the query
7113
7463
  * @param subquery - Subquery to check for existence
7114
7464
  * @returns New query builder instance with the WHERE EXISTS condition
7465
+ * @example
7466
+ * const postsQuery = new SelectQueryBuilder(postTable)
7467
+ * .where(eq(postTable.columns.userId, col('u.id')));
7468
+ * qb.whereExists(postsQuery);
7115
7469
  */
7116
7470
  whereExists(subquery, correlate) {
7117
7471
  const subAst = resolveSelectQuery(subquery);
@@ -7122,6 +7476,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7122
7476
  * Adds a WHERE NOT EXISTS condition to the query
7123
7477
  * @param subquery - Subquery to check for non-existence
7124
7478
  * @returns New query builder instance with the WHERE NOT EXISTS condition
7479
+ * @example
7480
+ * const postsQuery = new SelectQueryBuilder(postTable)
7481
+ * .where(eq(postTable.columns.userId, col('u.id')));
7482
+ * qb.whereNotExists(postsQuery); // Users without posts
7125
7483
  */
7126
7484
  whereNotExists(subquery, correlate) {
7127
7485
  const subAst = resolveSelectQuery(subquery);
@@ -7176,6 +7534,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7176
7534
  * Compiles the query to SQL for a specific dialect
7177
7535
  * @param dialect - Database dialect to compile for
7178
7536
  * @returns Compiled query with SQL and parameters
7537
+ * @example
7538
+ * const compiled = qb.select('id', 'name')
7539
+ * .where(eq(userTable.columns.active, true))
7540
+ * .compile('postgres');
7541
+ * console.log(compiled.sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
7179
7542
  */
7180
7543
  compile(dialect) {
7181
7544
  const resolved = resolveDialectInput(dialect);
@@ -7185,6 +7548,11 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7185
7548
  * Converts the query to SQL string for a specific dialect
7186
7549
  * @param dialect - Database dialect to generate SQL for
7187
7550
  * @returns SQL string representation of the query
7551
+ * @example
7552
+ * const sql = qb.select('id', 'name')
7553
+ * .where(eq(userTable.columns.active, true))
7554
+ * .toSql('postgres');
7555
+ * console.log(sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
7188
7556
  */
7189
7557
  toSql(dialect) {
7190
7558
  return this.compile(dialect).sql;
@@ -7192,6 +7560,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7192
7560
  /**
7193
7561
  * Gets the hydration plan for the query
7194
7562
  * @returns Hydration plan or undefined if none exists
7563
+ * @example
7564
+ * const plan = qb.include('posts').getHydrationPlan();
7565
+ * console.log(plan?.relations); // Information about included relations
7195
7566
  */
7196
7567
  getHydrationPlan() {
7197
7568
  return this.context.hydration.getPlan();
@@ -7199,6 +7570,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
7199
7570
  /**
7200
7571
  * Gets the Abstract Syntax Tree (AST) representation of the query
7201
7572
  * @returns Query AST with hydration applied
7573
+ * @example
7574
+ * const ast = qb.select('id', 'name').getAST();
7575
+ * console.log(ast.columns); // Array of column nodes
7576
+ * console.log(ast.from); // From clause information
7202
7577
  */
7203
7578
  getAST() {
7204
7579
  return this.context.hydration.applyToAst(this.context.state.ast);
@@ -7229,61 +7604,6 @@ var isTableDef = (value) => {
7229
7604
  return true;
7230
7605
  };
7231
7606
 
7232
- // src/orm/entity-metadata.ts
7233
- var metadataMap = /* @__PURE__ */ new Map();
7234
- var ensureEntityMetadata = (target) => {
7235
- let meta = metadataMap.get(target);
7236
- if (!meta) {
7237
- meta = {
7238
- target,
7239
- tableName: target.name || "unknown",
7240
- columns: {},
7241
- relations: {}
7242
- };
7243
- metadataMap.set(target, meta);
7244
- }
7245
- return meta;
7246
- };
7247
- var getEntityMetadata = (target) => {
7248
- return metadataMap.get(target);
7249
- };
7250
- var getAllEntityMetadata = () => {
7251
- return Array.from(metadataMap.values());
7252
- };
7253
- var addColumnMetadata = (target, propertyKey, column) => {
7254
- const meta = ensureEntityMetadata(target);
7255
- meta.columns[propertyKey] = { ...column };
7256
- };
7257
- var addRelationMetadata = (target, propertyKey, relation) => {
7258
- const meta = ensureEntityMetadata(target);
7259
- meta.relations[propertyKey] = relation;
7260
- };
7261
- var setEntityTableName = (target, tableName, hooks) => {
7262
- const meta = ensureEntityMetadata(target);
7263
- if (tableName && tableName.length > 0) {
7264
- meta.tableName = tableName;
7265
- }
7266
- if (hooks) {
7267
- meta.hooks = hooks;
7268
- }
7269
- };
7270
- var buildTableDef = (meta) => {
7271
- if (meta.table) {
7272
- return meta.table;
7273
- }
7274
- const columns = {};
7275
- for (const [key, def] of Object.entries(meta.columns)) {
7276
- columns[key] = {
7277
- ...def,
7278
- name: key,
7279
- table: meta.tableName
7280
- };
7281
- }
7282
- const table = defineTable(meta.tableName, columns, {}, meta.hooks);
7283
- meta.table = table;
7284
- return table;
7285
- };
7286
-
7287
7607
  // src/decorators/bootstrap.ts
7288
7608
  var unwrapTarget = (target) => {
7289
7609
  if (typeof target === "function" && target.prototype === void 0) {
@@ -7403,7 +7723,15 @@ var selectFromEntity = (ctor) => {
7403
7723
  if (!table) {
7404
7724
  throw new Error(`Entity '${ctor.name}' is not registered with decorators or has not been bootstrapped`);
7405
7725
  }
7406
- return new SelectQueryBuilder(table);
7726
+ return new SelectQueryBuilder(
7727
+ table,
7728
+ void 0,
7729
+ void 0,
7730
+ void 0,
7731
+ void 0,
7732
+ void 0,
7733
+ ctor
7734
+ );
7407
7735
  };
7408
7736
  var entityRef = (ctor) => {
7409
7737
  const table = getTableDefFromEntity(ctor);
@@ -8085,6 +8413,39 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
8085
8413
  };
8086
8414
  var isTableSourceNode2 = (source) => typeof source.type === "string";
8087
8415
 
8416
+ // src/query/target.ts
8417
+ var resolveEntityTarget = (ctor) => {
8418
+ const table = getTableDefFromEntity(ctor);
8419
+ if (!table) {
8420
+ throw new Error(`Entity '${ctor.name}' is not registered with decorators`);
8421
+ }
8422
+ return table;
8423
+ };
8424
+ var resolveTable = (target) => {
8425
+ if (isTableDef(target)) {
8426
+ return target;
8427
+ }
8428
+ return resolveEntityTarget(target);
8429
+ };
8430
+
8431
+ // src/query/index.ts
8432
+ var selectFrom = (target) => {
8433
+ const table = resolveTable(target);
8434
+ return new SelectQueryBuilder(table);
8435
+ };
8436
+ var insertInto = (target) => {
8437
+ const table = resolveTable(target);
8438
+ return new InsertQueryBuilder(table);
8439
+ };
8440
+ var update = (target) => {
8441
+ const table = resolveTable(target);
8442
+ return new UpdateQueryBuilder(table);
8443
+ };
8444
+ var deleteFrom = (target) => {
8445
+ const table = resolveTable(target);
8446
+ return new DeleteQueryBuilder(table);
8447
+ };
8448
+
8088
8449
  // src/core/ddl/sql-writing.ts
8089
8450
  var resolvePrimaryKey = (table) => {
8090
8451
  if (Array.isArray(table.primaryKey) && table.primaryKey.length > 0) {
@@ -12616,7 +12977,9 @@ function createPooledExecutorFactory(opts) {
12616
12977
  BelongsTo,
12617
12978
  BelongsToMany,
12618
12979
  Column,
12980
+ ConstructorMaterializationStrategy,
12619
12981
  DefaultBelongsToReference,
12982
+ DefaultEntityMaterializer,
12620
12983
  DefaultHasManyCollection,
12621
12984
  DefaultManyToManyCollection,
12622
12985
  DeleteQueryBuilder,
@@ -12632,6 +12995,7 @@ function createPooledExecutorFactory(opts) {
12632
12995
  Pool,
12633
12996
  PostgresDialect,
12634
12997
  PrimaryKey,
12998
+ PrototypeMaterializationStrategy,
12635
12999
  RelationKinds,
12636
13000
  STANDARD_COLUMN_TYPES,
12637
13001
  SelectQueryBuilder,
@@ -12703,6 +13067,7 @@ function createPooledExecutorFactory(opts) {
12703
13067
  dayOfWeek,
12704
13068
  defineTable,
12705
13069
  degrees,
13070
+ deleteFrom,
12706
13071
  denseRank,
12707
13072
  diffSchema,
12708
13073
  div,
@@ -12739,6 +13104,7 @@ function createPooledExecutorFactory(opts) {
12739
13104
  inList,
12740
13105
  inSubquery,
12741
13106
  initcap,
13107
+ insertInto,
12742
13108
  instr,
12743
13109
  introspectSchema,
12744
13110
  isCaseExpressionNode,
@@ -12781,6 +13147,7 @@ function createPooledExecutorFactory(opts) {
12781
13147
  lt,
12782
13148
  lte,
12783
13149
  ltrim,
13150
+ materializeAs,
12784
13151
  max,
12785
13152
  md5,
12786
13153
  min,
@@ -12827,6 +13194,7 @@ function createPooledExecutorFactory(opts) {
12827
13194
  rtrim,
12828
13195
  second,
12829
13196
  sel,
13197
+ selectFrom,
12830
13198
  selectFromEntity,
12831
13199
  setRelations,
12832
13200
  sha1,
@@ -12850,6 +13218,7 @@ function createPooledExecutorFactory(opts) {
12850
13218
  trunc,
12851
13219
  truncate,
12852
13220
  unixTimestamp,
13221
+ update,
12853
13222
  upper,
12854
13223
  utcNow,
12855
13224
  valueToOperand,