metal-orm 1.0.40 → 1.0.42

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.
Files changed (45) hide show
  1. package/README.md +53 -14
  2. package/dist/index.cjs +1298 -126
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +676 -30
  5. package/dist/index.d.ts +676 -30
  6. package/dist/index.js +1293 -126
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/codegen/typescript.ts +6 -2
  10. package/src/core/ast/expression-builders.ts +25 -4
  11. package/src/core/ast/expression-nodes.ts +3 -1
  12. package/src/core/ast/expression.ts +2 -2
  13. package/src/core/ast/query.ts +24 -2
  14. package/src/core/dialect/abstract.ts +6 -2
  15. package/src/core/dialect/base/join-compiler.ts +9 -12
  16. package/src/core/dialect/base/sql-dialect.ts +98 -17
  17. package/src/core/dialect/mssql/index.ts +30 -62
  18. package/src/core/dialect/sqlite/index.ts +39 -34
  19. package/src/core/execution/db-executor.ts +46 -6
  20. package/src/core/execution/executors/mssql-executor.ts +39 -22
  21. package/src/core/execution/executors/mysql-executor.ts +23 -6
  22. package/src/core/execution/executors/sqlite-executor.ts +29 -3
  23. package/src/core/execution/pooling/pool-types.ts +30 -0
  24. package/src/core/execution/pooling/pool.ts +268 -0
  25. package/src/decorators/bootstrap.ts +7 -7
  26. package/src/index.ts +6 -0
  27. package/src/orm/domain-event-bus.ts +49 -0
  28. package/src/orm/entity-metadata.ts +9 -9
  29. package/src/orm/entity.ts +58 -0
  30. package/src/orm/orm-session.ts +465 -270
  31. package/src/orm/orm.ts +61 -11
  32. package/src/orm/pooled-executor-factory.ts +131 -0
  33. package/src/orm/query-logger.ts +6 -12
  34. package/src/orm/relation-change-processor.ts +75 -0
  35. package/src/orm/relations/many-to-many.ts +4 -2
  36. package/src/orm/save-graph.ts +303 -0
  37. package/src/orm/transaction-runner.ts +3 -3
  38. package/src/orm/unit-of-work.ts +128 -0
  39. package/src/query-builder/delete-query-state.ts +67 -38
  40. package/src/query-builder/delete.ts +37 -1
  41. package/src/query-builder/insert-query-state.ts +131 -61
  42. package/src/query-builder/insert.ts +27 -1
  43. package/src/query-builder/update-query-state.ts +114 -77
  44. package/src/query-builder/update.ts +38 -1
  45. package/src/schema/table.ts +210 -115
package/README.md CHANGED
@@ -171,6 +171,7 @@ MetalORM can be just a straightforward query builder.
171
171
  import mysql from 'mysql2/promise';
172
172
  import {
173
173
  defineTable,
174
+ tableRef,
174
175
  col,
175
176
  SelectQueryBuilder,
176
177
  eq,
@@ -187,15 +188,14 @@ const todos = defineTable('todos', {
187
188
  todos.columns.title.notNull = true;
188
189
  todos.columns.done.default = false;
189
190
 
191
+ // Optional: opt-in ergonomic column access
192
+ const t = tableRef(todos);
193
+
190
194
  // 2) Build a simple query
191
195
  const listOpenTodos = new SelectQueryBuilder(todos)
192
- .select({
193
- id: todos.columns.id,
194
- title: todos.columns.title,
195
- done: todos.columns.done,
196
- })
197
- .where(eq(todos.columns.done, false))
198
- .orderBy(todos.columns.id, 'ASC');
196
+ .selectColumns('id', 'title', 'done')
197
+ .where(eq(t.done, false))
198
+ .orderBy(t.id, 'ASC');
199
199
 
200
200
  // 3) Compile to SQL + params
201
201
  const dialect = new MySqlDialect();
@@ -214,6 +214,48 @@ console.log(rows);
214
214
 
215
215
  That’s it: schema, query, SQL, done.
216
216
 
217
+ #### Column pickers (preferred selection helpers)
218
+
219
+ `defineTable` still exposes the full `table.columns` map for schema metadata and constraint tweaks, but modern queries usually benefit from higher-level helpers instead of spelling `todo.columns.*` everywhere.
220
+
221
+ ```ts
222
+ const t = tableRef(todos);
223
+
224
+ const listOpenTodos = new SelectQueryBuilder(todos)
225
+ .selectColumns('id', 'title', 'done') // typed shorthand for the same fields
226
+ .where(eq(t.done, false))
227
+ .orderBy(t.id, 'ASC');
228
+ ```
229
+
230
+ `selectColumns`, `selectRelationColumns`, `includePick`, `selectColumnsDeep`, the `sel()` helpers for tables, and `esel()` for entities all build typed selection maps without repeating `table.columns.*`. Use those helpers when building query selections and reserve `table.columns.*` for schema definition, relations, or rare cases where you need a column reference outside of a picker. See the [Query Builder docs](./docs/query-builder.md#selection-helpers) for the reference, examples, and best practices for these helpers.
231
+
232
+ #### Ergonomic column access (opt-in) with `tableRef`
233
+
234
+ If you still want the convenience of accessing columns without spelling `.columns`, you can opt-in with `tableRef()`:
235
+
236
+ ```ts
237
+ import { tableRef, eq } from 'metal-orm';
238
+
239
+ // Existing style (always works)
240
+ const listOpenTodos = new SelectQueryBuilder(todos)
241
+ .selectColumns('id', 'title', 'done')
242
+ .where(eq(todos.columns.done, false))
243
+ .orderBy(todos.columns.id, 'ASC');
244
+
245
+ // Opt-in ergonomic style
246
+ const t = tableRef(todos);
247
+
248
+ const listOpenTodos2 = new SelectQueryBuilder(todos)
249
+ .selectColumns('id', 'title', 'done')
250
+ .where(eq(t.done, false))
251
+ .orderBy(t.id, 'ASC');
252
+ ```
253
+
254
+ Collision rule: real table fields win.
255
+
256
+ - `t.name` is the table name (string)
257
+ - `t.$.name` is the column definition for a colliding column name (escape hatch)
258
+
217
259
  #### 2. Relations & hydration (still no ORM)
218
260
 
219
261
  Now add relations and get nested objects, still without committing to a runtime.
@@ -227,6 +269,7 @@ import {
227
269
  eq,
228
270
  count,
229
271
  rowNumber,
272
+ sel,
230
273
  hydrateRows,
231
274
  } from 'metal-orm';
232
275
 
@@ -257,19 +300,15 @@ users.columns.email.unique = true;
257
300
  // Build a query with relation & window function
258
301
  const builder = new SelectQueryBuilder(users)
259
302
  .select({
260
- id: users.columns.id,
261
- name: users.columns.name,
262
- email: users.columns.email,
303
+ ...sel(users, 'id', 'name', 'email'),
263
304
  postCount: count(posts.columns.id),
264
- rank: rowNumber(), // window function helper
305
+ rank: rowNumber(), // window function helper
265
306
  })
266
307
  .leftJoin(posts, eq(posts.columns.userId, users.columns.id))
267
308
  .groupBy(users.columns.id, users.columns.name, users.columns.email)
268
309
  .orderBy(count(posts.columns.id), 'DESC')
269
310
  .limit(10)
270
- .include('posts', {
271
- columns: [posts.columns.id, posts.columns.title, posts.columns.createdAt],
272
- }); // eager relation for hydration
311
+ .includePick('posts', ['id', 'title', 'createdAt']); // eager relation for hydration
273
312
 
274
313
  const { sql, params } = builder.compile(dialect);
275
314
  const [rows] = await connection.execute(sql, params);