metal-orm 1.0.14 → 1.0.15

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 (115) hide show
  1. package/README.md +40 -45
  2. package/dist/decorators/index.cjs +1600 -27
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +6 -2
  5. package/dist/decorators/index.d.ts +6 -2
  6. package/dist/decorators/index.js +1599 -27
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +4608 -3429
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +511 -159
  11. package/dist/index.d.ts +511 -159
  12. package/dist/index.js +4526 -3415
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-CCp1oz9p.d.cts → select-Bkv8g8u_.d.cts} +193 -67
  15. package/dist/{select-CCp1oz9p.d.ts → select-Bkv8g8u_.d.ts} +193 -67
  16. package/package.json +1 -1
  17. package/src/codegen/typescript.ts +38 -35
  18. package/src/core/ast/adapters.ts +21 -0
  19. package/src/core/ast/aggregate-functions.ts +13 -13
  20. package/src/core/ast/builders.ts +56 -43
  21. package/src/core/ast/expression-builders.ts +34 -34
  22. package/src/core/ast/expression-nodes.ts +18 -16
  23. package/src/core/ast/expression-visitor.ts +122 -69
  24. package/src/core/ast/expression.ts +6 -4
  25. package/src/core/ast/join-metadata.ts +15 -0
  26. package/src/core/ast/join-node.ts +22 -20
  27. package/src/core/ast/join.ts +5 -5
  28. package/src/core/ast/query.ts +52 -88
  29. package/src/core/ast/types.ts +20 -0
  30. package/src/core/ast/window-functions.ts +55 -55
  31. package/src/core/ddl/dialects/base-schema-dialect.ts +20 -6
  32. package/src/core/ddl/dialects/mssql-schema-dialect.ts +32 -8
  33. package/src/core/ddl/dialects/mysql-schema-dialect.ts +21 -10
  34. package/src/core/ddl/dialects/postgres-schema-dialect.ts +52 -7
  35. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +23 -9
  36. package/src/core/ddl/introspect/catalogs/index.ts +1 -0
  37. package/src/core/ddl/introspect/catalogs/postgres.ts +143 -0
  38. package/src/core/ddl/introspect/context.ts +9 -0
  39. package/src/core/ddl/introspect/functions/postgres.ts +26 -0
  40. package/src/core/ddl/introspect/mssql.ts +149 -149
  41. package/src/core/ddl/introspect/mysql.ts +99 -99
  42. package/src/core/ddl/introspect/postgres.ts +245 -154
  43. package/src/core/ddl/introspect/registry.ts +26 -0
  44. package/src/core/ddl/introspect/run-select.ts +25 -0
  45. package/src/core/ddl/introspect/sqlite.ts +7 -7
  46. package/src/core/ddl/introspect/types.ts +23 -19
  47. package/src/core/ddl/introspect/utils.ts +1 -1
  48. package/src/core/ddl/naming-strategy.ts +10 -0
  49. package/src/core/ddl/schema-dialect.ts +41 -0
  50. package/src/core/ddl/schema-diff.ts +211 -179
  51. package/src/core/ddl/schema-generator.ts +16 -90
  52. package/src/core/ddl/schema-introspect.ts +25 -32
  53. package/src/core/ddl/schema-plan-executor.ts +17 -0
  54. package/src/core/ddl/schema-types.ts +46 -39
  55. package/src/core/ddl/sql-writing.ts +170 -0
  56. package/src/core/dialect/abstract.ts +144 -126
  57. package/src/core/dialect/base/cte-compiler.ts +33 -0
  58. package/src/core/dialect/base/function-table-formatter.ts +132 -0
  59. package/src/core/dialect/base/groupby-compiler.ts +21 -0
  60. package/src/core/dialect/base/join-compiler.ts +26 -0
  61. package/src/core/dialect/base/orderby-compiler.ts +21 -0
  62. package/src/core/dialect/base/pagination-strategy.ts +32 -0
  63. package/src/core/dialect/base/returning-strategy.ts +56 -0
  64. package/src/core/dialect/base/sql-dialect.ts +181 -204
  65. package/src/core/dialect/dialect-factory.ts +91 -0
  66. package/src/core/dialect/mssql/functions.ts +101 -0
  67. package/src/core/dialect/mssql/index.ts +128 -126
  68. package/src/core/dialect/mysql/functions.ts +101 -0
  69. package/src/core/dialect/mysql/index.ts +20 -18
  70. package/src/core/dialect/postgres/functions.ts +95 -0
  71. package/src/core/dialect/postgres/index.ts +30 -28
  72. package/src/core/dialect/sqlite/functions.ts +115 -0
  73. package/src/core/dialect/sqlite/index.ts +30 -28
  74. package/src/core/driver/database-driver.ts +11 -0
  75. package/src/core/driver/mssql-driver.ts +20 -0
  76. package/src/core/driver/mysql-driver.ts +20 -0
  77. package/src/core/driver/postgres-driver.ts +20 -0
  78. package/src/core/driver/sqlite-driver.ts +20 -0
  79. package/src/core/execution/db-executor.ts +63 -0
  80. package/src/core/execution/executors/mssql-executor.ts +39 -0
  81. package/src/core/execution/executors/mysql-executor.ts +47 -0
  82. package/src/core/execution/executors/postgres-executor.ts +32 -0
  83. package/src/core/execution/executors/sqlite-executor.ts +31 -0
  84. package/src/core/functions/datetime.ts +132 -0
  85. package/src/core/functions/numeric.ts +179 -0
  86. package/src/core/functions/standard-strategy.ts +47 -0
  87. package/src/core/functions/text.ts +147 -0
  88. package/src/core/functions/types.ts +18 -0
  89. package/src/core/hydration/types.ts +57 -0
  90. package/src/decorators/bootstrap.ts +10 -0
  91. package/src/decorators/relations.ts +15 -0
  92. package/src/index.ts +30 -19
  93. package/src/orm/entity-metadata.ts +7 -0
  94. package/src/orm/entity.ts +58 -27
  95. package/src/orm/hydration.ts +25 -17
  96. package/src/orm/lazy-batch.ts +46 -2
  97. package/src/orm/orm-context.ts +60 -60
  98. package/src/orm/query-logger.ts +1 -1
  99. package/src/orm/relation-change-processor.ts +43 -2
  100. package/src/orm/relations/has-one.ts +139 -0
  101. package/src/orm/transaction-runner.ts +1 -1
  102. package/src/orm/unit-of-work.ts +60 -60
  103. package/src/query-builder/delete.ts +22 -5
  104. package/src/query-builder/hydration-manager.ts +2 -1
  105. package/src/query-builder/hydration-planner.ts +8 -7
  106. package/src/query-builder/insert.ts +22 -5
  107. package/src/query-builder/relation-conditions.ts +9 -8
  108. package/src/query-builder/relation-service.ts +3 -2
  109. package/src/query-builder/select.ts +66 -61
  110. package/src/query-builder/update.ts +22 -5
  111. package/src/schema/column.ts +246 -246
  112. package/src/schema/relation.ts +35 -1
  113. package/src/schema/table.ts +28 -28
  114. package/src/schema/types.ts +41 -31
  115. package/src/orm/db-executor.ts +0 -11
package/README.md CHANGED
@@ -63,6 +63,7 @@ Full docs live in the `docs/` folder:
63
63
  - **Fluent query builder** over a real SQL AST
64
64
  (`SelectQueryBuilder`, `InsertQueryBuilder`, `UpdateQueryBuilder`, `DeleteQueryBuilder`).
65
65
  - **Advanced SQL**: CTEs, aggregates, window functions, subqueries, JSON, CASE, EXISTS.
66
+ - **String helpers**: `lower`, `upper`, `trim`, `ltrim/rtrim`, `concat/concatWs`, `substr/left/right`, `position/instr/locate`, `replace`, `repeat`, `lpad/rpad`, `space`, and more with dialect-aware rendering.
66
67
  - **Set operations**: `union`, `unionAll`, `intersect`, `except` across all dialects (ORDER/LIMIT apply to the combined result; hydration is disabled for compound queries so rows are returned as-is without collapsing duplicates).
67
68
  - **Expression builders**: `eq`, `and`, `or`, `between`, `inList`, `exists`, `jsonPath`, `caseWhen`, window functions like `rowNumber`, `rank`, `lag`, `lead`, etc., all backed by typed AST nodes.
68
69
  - **Relation-aware hydration**: turn flat rows into nested objects (`user.posts`, `user.roles`, etc.) using a hydration plan derived from the AST metadata.
@@ -102,9 +103,10 @@ If you like explicit model classes, you can add a thin decorator layer on top of
102
103
  - `@Column(...)` and `@PrimaryKey(...)` on properties; decorators collect column metadata and later build `TableDef`s from it.
103
104
  - Relation decorators:
104
105
  - `@HasMany({ target, foreignKey, ... })`
106
+ - `@HasOne({ target, foreignKey, ... })`
105
107
  - `@BelongsTo({ target, foreignKey, ... })`
106
108
  - `@BelongsToMany({ target, pivotTable, ... })`
107
- - `bootstrapEntities()` scans metadata, builds `TableDef`s, wires relations with the same `hasMany` / `belongsTo` / `belongsToMany` helpers you would use manually, and returns the resulting tables.
109
+ - `bootstrapEntities()` scans metadata, builds `TableDef`s, wires relations with the same `hasOne` / `hasMany` / `belongsTo` / `belongsToMany` helpers you would use manually, and returns the resulting tables.
108
110
  - `selectFromEntity(MyEntity)` lets you start a `SelectQueryBuilder` directly from the class.
109
111
 
110
112
  You don’t have to use decorators, but when you do, you’re still on the same AST + dialect + runtime foundation.
@@ -171,10 +173,13 @@ import {
171
173
 
172
174
  // 1) A very small table
173
175
  const todos = defineTable('todos', {
174
- id: col.int().primaryKey(),
175
- title: col.varchar(255).notNull(),
176
- done: col.boolean().default(false),
176
+ id: col.primaryKey(col.int()),
177
+ title: col.varchar(255),
178
+ done: col.boolean(),
177
179
  });
180
+ // Add constraints
181
+ todos.columns.title.notNull = true;
182
+ todos.columns.done.default = false;
178
183
 
179
184
  // 2) Build a simple query
180
185
  const listOpenTodos = new SelectQueryBuilder(todos)
@@ -220,20 +225,29 @@ import {
220
225
  } from 'metal-orm';
221
226
 
222
227
  const posts = defineTable('posts', {
223
- id: col.int().primaryKey(),
224
- title: col.varchar(255).notNull(),
225
- userId: col.int().notNull(),
226
- createdAt: col.timestamp().default('CURRENT_TIMESTAMP'),
228
+ id: col.primaryKey(col.int()),
229
+ title: col.varchar(255),
230
+ userId: col.int(),
231
+ createdAt: col.timestamp(),
227
232
  });
228
233
 
234
+ // Add constraints
235
+ posts.columns.title.notNull = true;
236
+ posts.columns.userId.notNull = true;
237
+
229
238
  const users = defineTable('users', {
230
- id: col.int().primaryKey(),
231
- name: col.varchar(255).notNull(),
232
- email: col.varchar(255).unique(),
233
- }, {
234
- posts: hasMany(posts, 'userId'),
239
+ id: col.primaryKey(col.int()),
240
+ name: col.varchar(255),
241
+ email: col.varchar(255),
235
242
  });
236
243
 
244
+ // Add relations and constraints
245
+ users.relations = {
246
+ posts: hasMany(posts, 'userId'),
247
+ };
248
+ users.columns.name.notNull = true;
249
+ users.columns.email.unique = true;
250
+
237
251
  // Build a query with relation & window function
238
252
  const builder = new SelectQueryBuilder(users)
239
253
  .select({
@@ -287,36 +301,23 @@ When you're ready, you can let MetalORM manage entities and relations for you.
287
301
  Instead of “naked objects”, your queries can return entities attached to an `OrmContext`:
288
302
 
289
303
  ```ts
304
+ import mysql from 'mysql2/promise';
290
305
  import {
291
306
  OrmContext,
292
307
  MySqlDialect,
293
308
  SelectQueryBuilder,
294
309
  eq,
310
+ createMysqlExecutor,
295
311
  } from 'metal-orm';
296
312
 
297
313
  // 1) Create an OrmContext for this request
314
+
315
+ const connection = await mysql.createConnection({ /* ... */ });
316
+ const executor = createMysqlExecutor(connection);
317
+
298
318
  const ctx = new OrmContext({
299
319
  dialect: new MySqlDialect(),
300
- executor: {
301
- async executeSql(sql, params) {
302
- const [rows] = await connection.execute(sql, params);
303
- // MetalORM expects columns + values; adapt as needed
304
- return [{
305
- columns: Object.keys(rows[0] ?? {}),
306
- values: rows.map(row => Object.values(row)),
307
- }];
308
- },
309
- // Optional: if you want MetalORM to handle transactions around saveChanges()
310
- async beginTransaction() {
311
- await connection.beginTransaction();
312
- },
313
- async commitTransaction() {
314
- await connection.commit();
315
- },
316
- async rollbackTransaction() {
317
- await connection.rollback();
318
- },
319
- },
320
+ executor,
320
321
  });
321
322
 
322
323
  // 2) Load entities with lazy relations
@@ -380,7 +381,7 @@ class User {
380
381
  @PrimaryKey(col.int())
381
382
  id!: number;
382
383
 
383
- @Column(col.varchar(255).notNull())
384
+ @Column(col.varchar(255))
384
385
  name!: string;
385
386
 
386
387
  @Column(col.varchar(255))
@@ -398,10 +399,10 @@ class Post {
398
399
  @PrimaryKey(col.int())
399
400
  id!: number;
400
401
 
401
- @Column(col.varchar(255).notNull())
402
+ @Column(col.varchar(255))
402
403
  title!: string;
403
404
 
404
- @Column(col.int().notNull())
405
+ @Column(col.int())
405
406
  userId!: number;
406
407
 
407
408
  @BelongsTo({
@@ -417,18 +418,11 @@ const tables = bootstrapEntities();
417
418
 
418
419
  // 2) Create OrmContext as before
419
420
  const connection = await mysql.createConnection({ /* ... */ });
421
+ const executor = createMysqlExecutor(connection);
420
422
 
421
423
  const ctx = new OrmContext({
422
424
  dialect: new MySqlDialect(),
423
- executor: {
424
- async executeSql(sql, params) {
425
- const [rows] = await connection.execute(sql, params);
426
- return [{
427
- columns: Object.keys(rows[0] ?? {}),
428
- values: rows.map(row => Object.values(row)),
429
- }];
430
- },
431
- },
425
+ executor,
432
426
  });
433
427
 
434
428
  // 3) Query starting from the entity class
@@ -475,6 +469,7 @@ Under the hood, MetalORM leans on well-known patterns:
475
469
 
476
470
  - **AST + dialect abstraction**: SQL is modeled as typed AST nodes, compiled by dialects that you can extend.
477
471
  - **Separation of concerns**: schema, AST, SQL compilation, execution, and ORM runtime are separate layers.
472
+ - **Executor abstraction**: built-in executor creators (`createMysqlExecutor`, `createPostgresExecutor`, etc.) provide a clean separation between database drivers and ORM operations.
478
473
  - **Unit of Work + Identity Map**: `OrmContext` coordinates changes and enforces one entity instance per row, following the [Unit of Work](https://en.wikipedia.org/wiki/Unit_of_work) and [Identity map](https://en.wikipedia.org/wiki/Identity_map_pattern) patterns.
479
474
  - **Domain events + interceptors**: decouple side-effects from persistence and let cross-cutting concerns hook into flush points, similar in spirit to domain events in [Domain-driven design](https://en.wikipedia.org/wiki/Domain-driven_design).
480
475