metal-orm 1.0.51 → 1.0.52

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
@@ -74,20 +74,21 @@ MetalORM is a TypeScript-first, AST-driven SQL toolkit you can dial up or down d
74
74
  <a id="documentation"></a>
75
75
  ## Documentation 📚
76
76
 
77
- Full docs live in the `docs/` folder:
78
-
79
- - [Introduction](https://github.com/celsowm/metal-orm/blob/main/docs/index.md)
80
- - [Getting Started](https://github.com/celsowm/metal-orm/blob/main/docs/getting-started.md)
81
- - [Level 3 Backend Tutorial](https://github.com/celsowm/metal-orm/blob/main/docs/level-3-backend-tutorial.md)
82
- - [Schema Definition](https://github.com/celsowm/metal-orm/blob/main/docs/schema-definition.md)
83
- - [Query Builder](https://github.com/celsowm/metal-orm/blob/main/docs/query-builder.md)
84
- - [DML Operations](https://github.com/celsowm/metal-orm/blob/main/docs/dml-operations.md)
85
- - [Hydration & Entities](https://github.com/celsowm/metal-orm/blob/main/docs/hydration.md)
86
- - [Runtime & Unit of Work](https://github.com/celsowm/metal-orm/blob/main/docs/runtime.md)
87
- - [Advanced Features](https://github.com/celsowm/metal-orm/blob/main/docs/advanced-features.md)
88
- - [Multi-Dialect Support](https://github.com/celsowm/metal-orm/blob/main/docs/multi-dialect-support.md)
89
- - [Schema Generation (DDL)](https://github.com/celsowm/metal-orm/blob/main/docs/schema-generation.md)
90
- - [API Reference](https://github.com/celsowm/metal-orm/blob/main/docs/api-reference.md)
77
+ Full docs live in the `docs/` folder:
78
+
79
+ - [Introduction](https://github.com/celsowm/metal-orm/blob/main/docs/index.md)
80
+ - [Getting Started](https://github.com/celsowm/metal-orm/blob/main/docs/getting-started.md)
81
+ - [Level 3 Backend Tutorial](https://github.com/celsowm/metal-orm/blob/main/docs/level-3-backend-tutorial.md)
82
+ - [Schema Definition](https://github.com/celsowm/metal-orm/blob/main/docs/schema-definition.md)
83
+ - [Query Builder](https://github.com/celsowm/metal-orm/blob/main/docs/query-builder.md)
84
+ - [DML Operations](https://github.com/celsowm/metal-orm/blob/main/docs/dml-operations.md)
85
+ - [Hydration & Entities](https://github.com/celsowm/metal-orm/blob/main/docs/hydration.md)
86
+ - [Runtime & Unit of Work](https://github.com/celsowm/metal-orm/blob/main/docs/runtime.md)
87
+ - [Save Graph](https://github.com/celsowm/metal-orm/blob/main/docs/save-graph.md)
88
+ - [Advanced Features](https://github.com/celsowm/metal-orm/blob/main/docs/advanced-features.md)
89
+ - [Multi-Dialect Support](https://github.com/celsowm/metal-orm/blob/main/docs/multi-dialect-support.md)
90
+ - [Schema Generation (DDL)](https://github.com/celsowm/metal-orm/blob/main/docs/schema-generation.md)
91
+ - [API Reference](https://github.com/celsowm/metal-orm/blob/main/docs/api-reference.md)
91
92
  - [DB ➜ TS Type Mapping](https://github.com/celsowm/metal-orm/blob/main/docs/db-to-ts-types.md)
92
93
 
93
94
  ---
package/dist/index.cjs CHANGED
@@ -163,6 +163,7 @@ __export(index_exports, {
163
163
  isValueOperandInput: () => isValueOperandInput,
164
164
  isWindowFunctionNode: () => isWindowFunctionNode,
165
165
  jsonPath: () => jsonPath,
166
+ jsonify: () => jsonify,
166
167
  lag: () => lag,
167
168
  lastValue: () => lastValue,
168
169
  lead: () => lead,
@@ -9521,18 +9522,30 @@ var runInTransaction = async (executor, action) => {
9521
9522
 
9522
9523
  // src/orm/save-graph.ts
9523
9524
  var toKey8 = (value) => value === null || value === void 0 ? "" : String(value);
9524
- var pickColumns = (table, payload) => {
9525
+ var coerceColumnValue = (table, columnName, value, options) => {
9526
+ if (options.coerce !== "json") return value;
9527
+ if (value === null || value === void 0) return value;
9528
+ const column = table.columns[columnName];
9529
+ if (!column) return value;
9530
+ const normalized = normalizeColumnType(column.type);
9531
+ const isDateLikeColumn = normalized === "date" || normalized === "datetime" || normalized === "timestamp" || normalized === "timestamptz";
9532
+ if (isDateLikeColumn && value instanceof Date) {
9533
+ return value.toISOString();
9534
+ }
9535
+ return value;
9536
+ };
9537
+ var pickColumns = (table, payload, options) => {
9525
9538
  const columns = {};
9526
9539
  for (const key of Object.keys(table.columns)) {
9527
9540
  if (payload[key] !== void 0) {
9528
- columns[key] = payload[key];
9541
+ columns[key] = coerceColumnValue(table, key, payload[key], options);
9529
9542
  }
9530
9543
  }
9531
9544
  return columns;
9532
9545
  };
9533
- var ensureEntity = (session, table, payload) => {
9546
+ var ensureEntity = (session, table, payload, options) => {
9534
9547
  const pk = findPrimaryKey(table);
9535
- const row = pickColumns(table, payload);
9548
+ const row = pickColumns(table, payload, options);
9536
9549
  const pkValue = payload[pk];
9537
9550
  if (pkValue !== void 0 && pkValue !== null) {
9538
9551
  const tracked = session.getEntity(table, pkValue);
@@ -9545,10 +9558,10 @@ var ensureEntity = (session, table, payload) => {
9545
9558
  }
9546
9559
  return createEntityFromRow(session, table, row);
9547
9560
  };
9548
- var assignColumns = (table, entity, payload) => {
9561
+ var assignColumns = (table, entity, payload, options) => {
9549
9562
  for (const key of Object.keys(table.columns)) {
9550
9563
  if (payload[key] !== void 0) {
9551
- entity[key] = payload[key];
9564
+ entity[key] = coerceColumnValue(table, key, payload[key], options);
9552
9565
  }
9553
9566
  }
9554
9567
  };
@@ -9575,8 +9588,8 @@ var handleHasMany = async (session, root, relationName, relation, payload, optio
9575
9588
  const asObj = typeof item === "object" ? item : { [targetPk]: item };
9576
9589
  const pkValue = asObj[targetPk];
9577
9590
  const current = findInCollectionByPk(existing, targetPk, pkValue) ?? (pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) : void 0);
9578
- const entity = current ?? ensureEntity(session, targetTable, asObj);
9579
- assignColumns(targetTable, entity, asObj);
9591
+ const entity = current ?? ensureEntity(session, targetTable, asObj, options);
9592
+ assignColumns(targetTable, entity, asObj, options);
9580
9593
  await applyGraphToEntity(session, targetTable, entity, asObj, options);
9581
9594
  if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
9582
9595
  collection.attach(entity);
@@ -9651,8 +9664,8 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
9651
9664
  }
9652
9665
  const asObj = item;
9653
9666
  const pkValue = asObj[targetPk];
9654
- const entity = pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) ?? ensureEntity(session, targetTable, asObj) : ensureEntity(session, targetTable, asObj);
9655
- assignColumns(targetTable, entity, asObj);
9667
+ const entity = pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) ?? ensureEntity(session, targetTable, asObj, options) : ensureEntity(session, targetTable, asObj, options);
9668
+ assignColumns(targetTable, entity, asObj, options);
9656
9669
  await applyGraphToEntity(session, targetTable, entity, asObj, options);
9657
9670
  if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
9658
9671
  collection.attach(entity);
@@ -9683,7 +9696,7 @@ var applyRelation = async (session, table, entity, relationName, relation, paylo
9683
9696
  }
9684
9697
  };
9685
9698
  var applyGraphToEntity = async (session, table, entity, payload, options) => {
9686
- assignColumns(table, entity, payload);
9699
+ assignColumns(table, entity, payload, options);
9687
9700
  for (const [relationName, relation] of Object.entries(table.relations)) {
9688
9701
  if (!(relationName in payload)) continue;
9689
9702
  await applyRelation(session, table, entity, relationName, relation, payload[relationName], options);
@@ -9694,7 +9707,7 @@ var saveGraphInternal = async (session, entityClass, payload, options = {}) => {
9694
9707
  if (!table) {
9695
9708
  throw new Error("Entity metadata has not been bootstrapped");
9696
9709
  }
9697
- const root = ensureEntity(session, table, payload);
9710
+ const root = ensureEntity(session, table, payload, options);
9698
9711
  await applyGraphToEntity(session, table, root, payload, options);
9699
9712
  return root;
9700
9713
  };
@@ -9877,13 +9890,6 @@ var OrmSession = class {
9877
9890
  async findMany(qb) {
9878
9891
  return executeHydrated(this, qb);
9879
9892
  }
9880
- /**
9881
- * Saves an entity graph (root + nested relations) based on a DTO-like payload.
9882
- * @param entityClass - Root entity constructor
9883
- * @param payload - DTO payload containing column values and nested relations
9884
- * @param options - Graph save options
9885
- * @returns The root entity instance
9886
- */
9887
9893
  async saveGraph(entityClass, payload, options) {
9888
9894
  const { transactional = true, ...graphOptions } = options ?? {};
9889
9895
  const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
@@ -10084,6 +10090,17 @@ var Orm = class {
10084
10090
  }
10085
10091
  };
10086
10092
 
10093
+ // src/orm/jsonify.ts
10094
+ var jsonify = (value) => {
10095
+ const record = value;
10096
+ const result = {};
10097
+ for (const key of Object.keys(record)) {
10098
+ const entry = record[key];
10099
+ result[key] = entry instanceof Date ? entry.toISOString() : entry;
10100
+ }
10101
+ return result;
10102
+ };
10103
+
10087
10104
  // src/decorators/decorator-metadata.ts
10088
10105
  var METADATA_KEY = "metal-orm:decorators";
10089
10106
  var isStandardDecoratorContext = (value) => {
@@ -10968,6 +10985,7 @@ function createPooledExecutorFactory(opts) {
10968
10985
  isValueOperandInput,
10969
10986
  isWindowFunctionNode,
10970
10987
  jsonPath,
10988
+ jsonify,
10971
10989
  lag,
10972
10990
  lastValue,
10973
10991
  lead,