metal-orm 1.0.99 → 1.0.101

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/README.md CHANGED
@@ -127,6 +127,7 @@ On top of the query builder, MetalORM ships a focused runtime managed by `Orm` a
127
127
  - **Identity map**: the same row becomes the same entity instance within a session (see the [Identity map pattern](https://en.wikipedia.org/wiki/Identity_map_pattern)).
128
128
  - **Unit of Work (`OrmSession`)** tracking New/Dirty/Removed entities and relation changes, inspired by the classic [Unit of Work pattern](https://en.wikipedia.org/wiki/Unit_of_work).
129
129
  - **Graph persistence**: mutate a whole object graph and flush once with `session.commit()`.
130
+ - **Partial updates**: use `session.patchGraph()` to update only specific fields of an entity and its relations (returns `null` if entity doesn't exist).
130
131
  - **Relation change processor** that knows how to deal with has-many and many-to-many pivot tables.
131
132
  - **Interceptors**: `beforeFlush` / `afterFlush` hooks for cross-cutting concerns (auditing, multi-tenant filters, soft delete filters, etc.).
132
133
  - **Domain events**: `addDomainEvent` and a DomainEventBus integrated into `session.commit()`, aligned with domain events from [Domain-driven design](https://en.wikipedia.org/wiki/Domain-driven_design).
package/dist/index.cjs CHANGED
@@ -2302,11 +2302,14 @@ var SqlDialectBase = class extends Dialect {
2302
2302
  compileUpdateAssignments(assignments, table, ctx) {
2303
2303
  return assignments.map((assignment) => {
2304
2304
  const col2 = assignment.column;
2305
- const target = this.compileQualifiedColumn(col2, table);
2305
+ const target = this.compileSetTarget(col2, table);
2306
2306
  const value = this.compileOperand(assignment.value, ctx);
2307
2307
  return `${target} = ${value}`;
2308
2308
  }).join(", ");
2309
2309
  }
2310
+ compileSetTarget(column, table) {
2311
+ return this.compileQualifiedColumn(column, table);
2312
+ }
2310
2313
  compileQualifiedColumn(column, table) {
2311
2314
  const baseTableName = table.name;
2312
2315
  const alias = table.alias;
@@ -2649,6 +2652,12 @@ var PostgresDialect = class extends SqlDialectBase {
2649
2652
  supportsReturning() {
2650
2653
  return true;
2651
2654
  }
2655
+ /**
2656
+ * PostgreSQL requires unqualified column names in SET clause
2657
+ */
2658
+ compileSetTarget(column, _table) {
2659
+ return this.quoteIdentifier(column.name);
2660
+ }
2652
2661
  };
2653
2662
 
2654
2663
  // src/core/dialect/mysql/functions.ts
@@ -12214,6 +12223,14 @@ var saveGraphInternal = async (session, entityClass, payload, options = {}) => {
12214
12223
  await applyGraphToEntity(session, table, root, payload, options);
12215
12224
  return root;
12216
12225
  };
12226
+ var patchGraphInternal = async (session, entityClass, existing, payload, options = {}) => {
12227
+ const table = getTableDefFromEntity(entityClass);
12228
+ if (!table) {
12229
+ throw new Error("Entity metadata has not been bootstrapped");
12230
+ }
12231
+ await applyGraphToEntity(session, table, existing, payload, options);
12232
+ return existing;
12233
+ };
12217
12234
 
12218
12235
  // src/orm/orm-session.ts
12219
12236
  var OrmSession = class {
@@ -12474,6 +12491,33 @@ var OrmSession = class {
12474
12491
  }
12475
12492
  return this.transaction(() => execute());
12476
12493
  }
12494
+ async patchGraph(entityClass, payload, options) {
12495
+ const table = getTableDefFromEntity(entityClass);
12496
+ if (!table) {
12497
+ throw new Error("Entity metadata has not been bootstrapped");
12498
+ }
12499
+ const primaryKey = findPrimaryKey(table);
12500
+ const pkValue = payload[primaryKey];
12501
+ if (pkValue === void 0 || pkValue === null) {
12502
+ throw new Error(`patchGraph requires a primary key value for "${primaryKey}"`);
12503
+ }
12504
+ const resolved = this.resolveSaveGraphOptions(options);
12505
+ const { transactional = true, flush = false, ...graphOptions } = resolved;
12506
+ const execute = async () => {
12507
+ const tracked = this.getEntity(table, pkValue);
12508
+ const existing = tracked ?? await this.find(entityClass, pkValue);
12509
+ if (!existing) return null;
12510
+ return patchGraphInternal(this, entityClass, existing, payload, graphOptions);
12511
+ };
12512
+ if (!transactional) {
12513
+ const result = await execute();
12514
+ if (result && flush) {
12515
+ await this.flush();
12516
+ }
12517
+ return result;
12518
+ }
12519
+ return this.transaction(() => execute());
12520
+ }
12477
12521
  /**
12478
12522
  * Persists an entity (either inserts or updates).
12479
12523
  * @param entity - The entity to persist