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 +15 -14
- package/dist/index.cjs +37 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -2
- package/dist/index.d.ts +54 -2
- package/dist/index.js +36 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -2
- package/src/orm/jsonify.ts +27 -0
- package/src/orm/orm-session.ts +28 -22
- package/src/orm/save-graph-types.ts +57 -0
- package/src/orm/save-graph.ts +141 -105
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
|
-
- [
|
|
88
|
-
- [
|
|
89
|
-
- [
|
|
90
|
-
- [
|
|
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
|
|
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,
|