metal-orm 1.0.50 → 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 +188 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -2
- package/dist/index.d.ts +58 -2
- package/dist/index.js +187 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-entities/render.mjs +115 -12
- package/scripts/inflection/compound.mjs +72 -0
- package/scripts/inflection/en.mjs +26 -0
- package/scripts/inflection/index.mjs +29 -0
- package/scripts/inflection/pt-br.mjs +391 -0
- package/scripts/naming-strategy.mjs +27 -63
- package/scripts/pt-pluralizer.mjs +19 -0
- package/src/core/ddl/introspect/mssql.ts +74 -2
- package/src/core/ddl/introspect/postgres.ts +69 -39
- package/src/core/ddl/introspect/sqlite.ts +69 -5
- 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/src/schema/column-types.ts +14 -9
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,
|
|
@@ -379,6 +380,10 @@ var col = {
|
|
|
379
380
|
* @returns ColumnDef with VARCHAR type
|
|
380
381
|
*/
|
|
381
382
|
varchar: (length2) => ({ name: "", type: "VARCHAR", args: [length2] }),
|
|
383
|
+
/**
|
|
384
|
+
* Creates a text column definition
|
|
385
|
+
*/
|
|
386
|
+
text: () => ({ name: "", type: "TEXT" }),
|
|
382
387
|
/**
|
|
383
388
|
* Creates a fixed precision decimal column definition
|
|
384
389
|
*/
|
|
@@ -6887,6 +6892,29 @@ var postgresIntrospector = {
|
|
|
6887
6892
|
if (!trimmed) return;
|
|
6888
6893
|
columnComments.set(key, trimmed);
|
|
6889
6894
|
});
|
|
6895
|
+
const tableCommentRows = await queryRows(
|
|
6896
|
+
ctx.executor,
|
|
6897
|
+
`
|
|
6898
|
+
SELECT
|
|
6899
|
+
ns.nspname AS table_schema,
|
|
6900
|
+
cls.relname AS table_name,
|
|
6901
|
+
pg_catalog.obj_description(cls.oid) AS description
|
|
6902
|
+
FROM pg_catalog.pg_class cls
|
|
6903
|
+
JOIN pg_catalog.pg_namespace ns ON ns.oid = cls.relnamespace
|
|
6904
|
+
WHERE ns.nspname = $1
|
|
6905
|
+
AND cls.relkind IN ('r', 'p')
|
|
6906
|
+
`,
|
|
6907
|
+
[schema]
|
|
6908
|
+
);
|
|
6909
|
+
const tableComments = /* @__PURE__ */ new Map();
|
|
6910
|
+
tableCommentRows.forEach((r) => {
|
|
6911
|
+
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
6912
|
+
if (!r.description) return;
|
|
6913
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
6914
|
+
const trimmed = r.description.trim();
|
|
6915
|
+
if (!trimmed) return;
|
|
6916
|
+
tableComments.set(key, trimmed);
|
|
6917
|
+
});
|
|
6890
6918
|
const qbPk = new SelectQueryBuilder(PgKeyColumnUsage).select({
|
|
6891
6919
|
table_schema: PgKeyColumnUsage.columns.table_schema,
|
|
6892
6920
|
table_name: PgKeyColumnUsage.columns.table_name,
|
|
@@ -7027,7 +7055,8 @@ var postgresIntrospector = {
|
|
|
7027
7055
|
schema: r.table_schema,
|
|
7028
7056
|
columns: [],
|
|
7029
7057
|
primaryKey: pkMap.get(key) || [],
|
|
7030
|
-
indexes: []
|
|
7058
|
+
indexes: [],
|
|
7059
|
+
comment: tableComments.get(key)
|
|
7031
7060
|
});
|
|
7032
7061
|
}
|
|
7033
7062
|
const cols = tablesByKey.get(key);
|
|
@@ -7412,6 +7441,53 @@ var runPragma = async (name, table, alias, columnAliases, ctx) => {
|
|
|
7412
7441
|
const query = buildPragmaQuery(name, table, alias, columnAliases);
|
|
7413
7442
|
return await runSelectNode(query, ctx);
|
|
7414
7443
|
};
|
|
7444
|
+
var loadSqliteSchemaComments = async (ctx) => {
|
|
7445
|
+
const tableComments = /* @__PURE__ */ new Map();
|
|
7446
|
+
const columnComments = /* @__PURE__ */ new Map();
|
|
7447
|
+
const tableExists = await queryRows(
|
|
7448
|
+
ctx.executor,
|
|
7449
|
+
`SELECT name FROM sqlite_master WHERE type='table' AND name='schema_comments' LIMIT 1`
|
|
7450
|
+
);
|
|
7451
|
+
if (!tableExists.length) {
|
|
7452
|
+
return { tableComments, columnComments };
|
|
7453
|
+
}
|
|
7454
|
+
const commentRows = await queryRows(
|
|
7455
|
+
ctx.executor,
|
|
7456
|
+
`SELECT object_type, schema_name, table_name, column_name, comment FROM schema_comments`
|
|
7457
|
+
);
|
|
7458
|
+
for (const row of commentRows) {
|
|
7459
|
+
const objectType = typeof row.object_type === "string" ? row.object_type.toLowerCase() : "";
|
|
7460
|
+
const tableName = typeof row.table_name === "string" ? row.table_name : "";
|
|
7461
|
+
if (!tableName) continue;
|
|
7462
|
+
const columnName = typeof row.column_name === "string" ? row.column_name : "";
|
|
7463
|
+
const schemaName = typeof row.schema_name === "string" ? row.schema_name : "";
|
|
7464
|
+
const rawComment = row.comment;
|
|
7465
|
+
if (rawComment == null) continue;
|
|
7466
|
+
const commentText = String(rawComment).trim();
|
|
7467
|
+
if (!commentText) continue;
|
|
7468
|
+
const addTableComment = () => {
|
|
7469
|
+
tableComments.set(tableName, commentText);
|
|
7470
|
+
if (schemaName) {
|
|
7471
|
+
tableComments.set(`${schemaName}.${tableName}`, commentText);
|
|
7472
|
+
}
|
|
7473
|
+
};
|
|
7474
|
+
const addColumnComment = () => {
|
|
7475
|
+
columnComments.set(`${tableName}.${columnName}`, commentText);
|
|
7476
|
+
if (schemaName) {
|
|
7477
|
+
columnComments.set(`${schemaName}.${tableName}.${columnName}`, commentText);
|
|
7478
|
+
}
|
|
7479
|
+
};
|
|
7480
|
+
if (objectType === "table") {
|
|
7481
|
+
addTableComment();
|
|
7482
|
+
} else if (objectType === "column" && columnName) {
|
|
7483
|
+
addColumnComment();
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
return {
|
|
7487
|
+
tableComments,
|
|
7488
|
+
columnComments
|
|
7489
|
+
};
|
|
7490
|
+
};
|
|
7415
7491
|
var sqliteIntrospector = {
|
|
7416
7492
|
async introspect(ctx, options) {
|
|
7417
7493
|
const alias = "sqlite_master";
|
|
@@ -7425,6 +7501,7 @@ var sqliteIntrospector = {
|
|
|
7425
7501
|
notLike(columnNode2(alias, "name"), "sqlite_%")
|
|
7426
7502
|
)
|
|
7427
7503
|
};
|
|
7504
|
+
const { tableComments, columnComments } = await loadSqliteSchemaComments(ctx);
|
|
7428
7505
|
const tableRows = await runSelectNode(tablesQuery, ctx);
|
|
7429
7506
|
const tables = [];
|
|
7430
7507
|
for (const row of tableRows) {
|
|
@@ -7451,15 +7528,26 @@ var sqliteIntrospector = {
|
|
|
7451
7528
|
["seq", "name", "unique"],
|
|
7452
7529
|
ctx
|
|
7453
7530
|
);
|
|
7454
|
-
const tableEntry = {
|
|
7531
|
+
const tableEntry = {
|
|
7532
|
+
name: tableName,
|
|
7533
|
+
columns: [],
|
|
7534
|
+
primaryKey: [],
|
|
7535
|
+
indexes: [],
|
|
7536
|
+
comment: tableComments.get(tableName)
|
|
7537
|
+
};
|
|
7455
7538
|
tableInfo.forEach((info) => {
|
|
7456
|
-
|
|
7539
|
+
const column = {
|
|
7457
7540
|
name: info.name,
|
|
7458
7541
|
type: info.type,
|
|
7459
7542
|
notNull: info.notnull === 1,
|
|
7460
7543
|
default: info.dflt_value ?? void 0,
|
|
7461
7544
|
autoIncrement: false
|
|
7462
|
-
}
|
|
7545
|
+
};
|
|
7546
|
+
const columnComment = columnComments.get(`${tableName}.${info.name}`);
|
|
7547
|
+
if (columnComment) {
|
|
7548
|
+
column.comment = columnComment;
|
|
7549
|
+
}
|
|
7550
|
+
tableEntry.columns.push(column);
|
|
7463
7551
|
if (info.pk && info.pk > 0) {
|
|
7464
7552
|
tableEntry.primaryKey = tableEntry.primaryKey || [];
|
|
7465
7553
|
tableEntry.primaryKey.push(info.name);
|
|
@@ -7731,6 +7819,60 @@ var mssqlIntrospector = {
|
|
|
7731
7819
|
async introspect(ctx, options) {
|
|
7732
7820
|
const schema = options.schema;
|
|
7733
7821
|
const schemaCondition = schema ? eq(columnNode3("sch", "name"), schema) : void 0;
|
|
7822
|
+
const schemaFilter = schema ? "AND sch.name = @p1" : "";
|
|
7823
|
+
const schemaParams = schema ? [schema] : [];
|
|
7824
|
+
const tableCommentRows = await queryRows(
|
|
7825
|
+
ctx.executor,
|
|
7826
|
+
`
|
|
7827
|
+
SELECT
|
|
7828
|
+
sch.name AS table_schema,
|
|
7829
|
+
t.name AS table_name,
|
|
7830
|
+
CONVERT(nvarchar(4000), ep.value) AS comment
|
|
7831
|
+
FROM sys.extended_properties ep
|
|
7832
|
+
JOIN sys.tables t ON t.object_id = ep.major_id
|
|
7833
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
7834
|
+
WHERE ep.class = 1
|
|
7835
|
+
AND ep.minor_id = 0
|
|
7836
|
+
AND ep.name = 'MS_Description'
|
|
7837
|
+
${schemaFilter}
|
|
7838
|
+
`,
|
|
7839
|
+
schemaParams
|
|
7840
|
+
);
|
|
7841
|
+
const columnCommentRows = await queryRows(
|
|
7842
|
+
ctx.executor,
|
|
7843
|
+
`
|
|
7844
|
+
SELECT
|
|
7845
|
+
sch.name AS table_schema,
|
|
7846
|
+
t.name AS table_name,
|
|
7847
|
+
col.name AS column_name,
|
|
7848
|
+
CONVERT(nvarchar(4000), ep.value) AS comment
|
|
7849
|
+
FROM sys.extended_properties ep
|
|
7850
|
+
JOIN sys.columns col ON col.object_id = ep.major_id AND col.column_id = ep.minor_id
|
|
7851
|
+
JOIN sys.tables t ON t.object_id = col.object_id
|
|
7852
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
7853
|
+
WHERE ep.class = 1
|
|
7854
|
+
AND ep.minor_id > 0
|
|
7855
|
+
AND ep.name = 'MS_Description'
|
|
7856
|
+
${schemaFilter}
|
|
7857
|
+
`,
|
|
7858
|
+
schemaParams
|
|
7859
|
+
);
|
|
7860
|
+
const tableComments = /* @__PURE__ */ new Map();
|
|
7861
|
+
tableCommentRows.forEach((r) => {
|
|
7862
|
+
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
7863
|
+
if (!r.comment) return;
|
|
7864
|
+
const trimmed = r.comment.trim();
|
|
7865
|
+
if (!trimmed) return;
|
|
7866
|
+
tableComments.set(`${r.table_schema}.${r.table_name}`, trimmed);
|
|
7867
|
+
});
|
|
7868
|
+
const columnComments = /* @__PURE__ */ new Map();
|
|
7869
|
+
columnCommentRows.forEach((r) => {
|
|
7870
|
+
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
7871
|
+
if (!r.comment) return;
|
|
7872
|
+
const trimmed = r.comment.trim();
|
|
7873
|
+
if (!trimmed) return;
|
|
7874
|
+
columnComments.set(`${r.table_schema}.${r.table_name}.${r.column_name}`, trimmed);
|
|
7875
|
+
});
|
|
7734
7876
|
const dataTypeExpression = buildMssqlDataType(
|
|
7735
7877
|
{ table: "ty", name: "name" },
|
|
7736
7878
|
{ table: "c", name: "max_length" },
|
|
@@ -8036,7 +8178,8 @@ var mssqlIntrospector = {
|
|
|
8036
8178
|
schema: r.table_schema,
|
|
8037
8179
|
columns: [],
|
|
8038
8180
|
primaryKey: pkMap.get(key) || [],
|
|
8039
|
-
indexes: []
|
|
8181
|
+
indexes: [],
|
|
8182
|
+
comment: tableComments.get(key)
|
|
8040
8183
|
});
|
|
8041
8184
|
}
|
|
8042
8185
|
const table = tablesByKey.get(key);
|
|
@@ -8047,6 +8190,10 @@ var mssqlIntrospector = {
|
|
|
8047
8190
|
default: r.column_default ?? void 0,
|
|
8048
8191
|
autoIncrement: !!r.is_identity
|
|
8049
8192
|
};
|
|
8193
|
+
const columnComment = columnComments.get(`${key}.${r.column_name}`);
|
|
8194
|
+
if (columnComment) {
|
|
8195
|
+
column.comment = columnComment;
|
|
8196
|
+
}
|
|
8050
8197
|
const fk = fkMap.get(`${key}.${r.column_name}`)?.[0];
|
|
8051
8198
|
if (fk) {
|
|
8052
8199
|
column.references = {
|
|
@@ -9375,18 +9522,30 @@ var runInTransaction = async (executor, action) => {
|
|
|
9375
9522
|
|
|
9376
9523
|
// src/orm/save-graph.ts
|
|
9377
9524
|
var toKey8 = (value) => value === null || value === void 0 ? "" : String(value);
|
|
9378
|
-
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) => {
|
|
9379
9538
|
const columns = {};
|
|
9380
9539
|
for (const key of Object.keys(table.columns)) {
|
|
9381
9540
|
if (payload[key] !== void 0) {
|
|
9382
|
-
columns[key] = payload[key];
|
|
9541
|
+
columns[key] = coerceColumnValue(table, key, payload[key], options);
|
|
9383
9542
|
}
|
|
9384
9543
|
}
|
|
9385
9544
|
return columns;
|
|
9386
9545
|
};
|
|
9387
|
-
var ensureEntity = (session, table, payload) => {
|
|
9546
|
+
var ensureEntity = (session, table, payload, options) => {
|
|
9388
9547
|
const pk = findPrimaryKey(table);
|
|
9389
|
-
const row = pickColumns(table, payload);
|
|
9548
|
+
const row = pickColumns(table, payload, options);
|
|
9390
9549
|
const pkValue = payload[pk];
|
|
9391
9550
|
if (pkValue !== void 0 && pkValue !== null) {
|
|
9392
9551
|
const tracked = session.getEntity(table, pkValue);
|
|
@@ -9399,10 +9558,10 @@ var ensureEntity = (session, table, payload) => {
|
|
|
9399
9558
|
}
|
|
9400
9559
|
return createEntityFromRow(session, table, row);
|
|
9401
9560
|
};
|
|
9402
|
-
var assignColumns = (table, entity, payload) => {
|
|
9561
|
+
var assignColumns = (table, entity, payload, options) => {
|
|
9403
9562
|
for (const key of Object.keys(table.columns)) {
|
|
9404
9563
|
if (payload[key] !== void 0) {
|
|
9405
|
-
entity[key] = payload[key];
|
|
9564
|
+
entity[key] = coerceColumnValue(table, key, payload[key], options);
|
|
9406
9565
|
}
|
|
9407
9566
|
}
|
|
9408
9567
|
};
|
|
@@ -9429,8 +9588,8 @@ var handleHasMany = async (session, root, relationName, relation, payload, optio
|
|
|
9429
9588
|
const asObj = typeof item === "object" ? item : { [targetPk]: item };
|
|
9430
9589
|
const pkValue = asObj[targetPk];
|
|
9431
9590
|
const current = findInCollectionByPk(existing, targetPk, pkValue) ?? (pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) : void 0);
|
|
9432
|
-
const entity = current ?? ensureEntity(session, targetTable, asObj);
|
|
9433
|
-
assignColumns(targetTable, entity, asObj);
|
|
9591
|
+
const entity = current ?? ensureEntity(session, targetTable, asObj, options);
|
|
9592
|
+
assignColumns(targetTable, entity, asObj, options);
|
|
9434
9593
|
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
9435
9594
|
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
9436
9595
|
collection.attach(entity);
|
|
@@ -9505,8 +9664,8 @@ var handleBelongsToMany = async (session, root, relationName, relation, payload,
|
|
|
9505
9664
|
}
|
|
9506
9665
|
const asObj = item;
|
|
9507
9666
|
const pkValue = asObj[targetPk];
|
|
9508
|
-
const entity = pkValue !== void 0 && pkValue !== null ? session.getEntity(targetTable, pkValue) ?? ensureEntity(session, targetTable, asObj) : ensureEntity(session, targetTable, asObj);
|
|
9509
|
-
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);
|
|
9510
9669
|
await applyGraphToEntity(session, targetTable, entity, asObj, options);
|
|
9511
9670
|
if (!isEntityInCollection(collection.getItems(), targetPk, entity)) {
|
|
9512
9671
|
collection.attach(entity);
|
|
@@ -9537,7 +9696,7 @@ var applyRelation = async (session, table, entity, relationName, relation, paylo
|
|
|
9537
9696
|
}
|
|
9538
9697
|
};
|
|
9539
9698
|
var applyGraphToEntity = async (session, table, entity, payload, options) => {
|
|
9540
|
-
assignColumns(table, entity, payload);
|
|
9699
|
+
assignColumns(table, entity, payload, options);
|
|
9541
9700
|
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
9542
9701
|
if (!(relationName in payload)) continue;
|
|
9543
9702
|
await applyRelation(session, table, entity, relationName, relation, payload[relationName], options);
|
|
@@ -9548,7 +9707,7 @@ var saveGraphInternal = async (session, entityClass, payload, options = {}) => {
|
|
|
9548
9707
|
if (!table) {
|
|
9549
9708
|
throw new Error("Entity metadata has not been bootstrapped");
|
|
9550
9709
|
}
|
|
9551
|
-
const root = ensureEntity(session, table, payload);
|
|
9710
|
+
const root = ensureEntity(session, table, payload, options);
|
|
9552
9711
|
await applyGraphToEntity(session, table, root, payload, options);
|
|
9553
9712
|
return root;
|
|
9554
9713
|
};
|
|
@@ -9731,13 +9890,6 @@ var OrmSession = class {
|
|
|
9731
9890
|
async findMany(qb) {
|
|
9732
9891
|
return executeHydrated(this, qb);
|
|
9733
9892
|
}
|
|
9734
|
-
/**
|
|
9735
|
-
* Saves an entity graph (root + nested relations) based on a DTO-like payload.
|
|
9736
|
-
* @param entityClass - Root entity constructor
|
|
9737
|
-
* @param payload - DTO payload containing column values and nested relations
|
|
9738
|
-
* @param options - Graph save options
|
|
9739
|
-
* @returns The root entity instance
|
|
9740
|
-
*/
|
|
9741
9893
|
async saveGraph(entityClass, payload, options) {
|
|
9742
9894
|
const { transactional = true, ...graphOptions } = options ?? {};
|
|
9743
9895
|
const execute = () => saveGraphInternal(this, entityClass, payload, graphOptions);
|
|
@@ -9938,6 +10090,17 @@ var Orm = class {
|
|
|
9938
10090
|
}
|
|
9939
10091
|
};
|
|
9940
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
|
+
|
|
9941
10104
|
// src/decorators/decorator-metadata.ts
|
|
9942
10105
|
var METADATA_KEY = "metal-orm:decorators";
|
|
9943
10106
|
var isStandardDecoratorContext = (value) => {
|
|
@@ -10822,6 +10985,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
10822
10985
|
isValueOperandInput,
|
|
10823
10986
|
isWindowFunctionNode,
|
|
10824
10987
|
jsonPath,
|
|
10988
|
+
jsonify,
|
|
10825
10989
|
lag,
|
|
10826
10990
|
lastValue,
|
|
10827
10991
|
lead,
|