spice-js 2.6.74 → 2.6.76
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/build/models/SpiceModel.js +97 -26
- package/package.json +1 -1
- package/src/models/SpiceModel.js +98 -19
|
@@ -36,7 +36,8 @@ var SDate = require("sonover-date"),
|
|
|
36
36
|
_skip_cache = Symbol(),
|
|
37
37
|
_serializers = Symbol(),
|
|
38
38
|
_level = Symbol(),
|
|
39
|
-
_mapping_dept = Symbol()
|
|
39
|
+
_mapping_dept = Symbol(),
|
|
40
|
+
_mapping_dept_exempt = Symbol(); //const _type = Symbol("type");
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
var that;
|
|
@@ -59,21 +60,22 @@ class SpiceModel {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
try {
|
|
62
|
-
var _args2, _args2$args,
|
|
63
|
+
var _args2, _args2$args, _args3, _args3$args, _args$args, _args4, _args4$args, _args5, _args5$args, _args6, _args6$args;
|
|
63
64
|
|
|
64
65
|
var dbtype = spice.config.database.connections[args.connection].type || "couchbase";
|
|
65
66
|
|
|
66
67
|
var Database = require("spice-" + dbtype);
|
|
67
68
|
|
|
68
69
|
this[_mapping_dept] = ((_args2 = args) == null ? void 0 : (_args2$args = _args2.args) == null ? void 0 : _args2$args.mapping_dept) || 100;
|
|
70
|
+
this[_mapping_dept_exempt] = ((_args3 = args) == null ? void 0 : (_args3$args = _args3.args) == null ? void 0 : _args3$args.mapping_dept_exempt) || [];
|
|
69
71
|
this.type = "";
|
|
70
72
|
this.collection = args.connection;
|
|
71
73
|
this[_args] = args.args;
|
|
72
74
|
this[_external_modifier_loaded] = false;
|
|
73
75
|
this[_disable_lifecycle_events] = ((_args$args = args.args) == null ? void 0 : _args$args.disable_lifecycle_events) || false;
|
|
74
|
-
this[_ctx] = (
|
|
75
|
-
this[_skip_cache] = ((
|
|
76
|
-
this[_level] = ((
|
|
76
|
+
this[_ctx] = (_args4 = args) == null ? void 0 : (_args4$args = _args4.args) == null ? void 0 : _args4$args.ctx;
|
|
77
|
+
this[_skip_cache] = ((_args5 = args) == null ? void 0 : (_args5$args = _args5.args) == null ? void 0 : _args5$args.skip_cache) || false;
|
|
78
|
+
this[_level] = ((_args6 = args) == null ? void 0 : (_args6$args = _args6.args) == null ? void 0 : _args6$args._level) || 0;
|
|
77
79
|
this[_hooks] = {
|
|
78
80
|
create: {
|
|
79
81
|
before: [],
|
|
@@ -576,6 +578,7 @@ class SpiceModel {
|
|
|
576
578
|
function () {
|
|
577
579
|
var _ref2 = _asyncToGenerator(function* () {
|
|
578
580
|
if (args.mapping_dept) _this4[_mapping_dept] = args.mapping_dept;
|
|
581
|
+
if (args.mapping_dept_exempt) _this4[_mapping_dept_exempt] = args.mapping_dept_exempt;
|
|
579
582
|
|
|
580
583
|
if (!args) {
|
|
581
584
|
args = {};
|
|
@@ -668,10 +671,10 @@ class SpiceModel {
|
|
|
668
671
|
|
|
669
672
|
try {
|
|
670
673
|
if (p) {
|
|
671
|
-
var
|
|
674
|
+
var _args7;
|
|
672
675
|
|
|
673
676
|
return yield p.track(_this4.type + ".get", doGet, {
|
|
674
|
-
id: (
|
|
677
|
+
id: (_args7 = args) == null ? void 0 : _args7.id
|
|
675
678
|
});
|
|
676
679
|
}
|
|
677
680
|
|
|
@@ -1316,11 +1319,12 @@ class SpiceModel {
|
|
|
1316
1319
|
/*#__PURE__*/
|
|
1317
1320
|
function () {
|
|
1318
1321
|
var _ref12 = _asyncToGenerator(function* () {
|
|
1319
|
-
var
|
|
1322
|
+
var _args8, _args9, _args10;
|
|
1320
1323
|
|
|
1321
|
-
if (args.mapping_dept) _this12[_mapping_dept] = args.mapping_dept;
|
|
1324
|
+
if (args.mapping_dept) _this12[_mapping_dept] = args.mapping_dept;
|
|
1325
|
+
if (args.mapping_dept_exempt) _this12[_mapping_dept_exempt] = args.mapping_dept_exempt; // Find alias tokens from query/columns/sort
|
|
1322
1326
|
|
|
1323
|
-
var nestings = [..._this12.extractNestings(((
|
|
1327
|
+
var nestings = [..._this12.extractNestings(((_args8 = args) == null ? void 0 : _args8.query) || "", _this12.type), ..._this12.extractNestings(((_args9 = args) == null ? void 0 : _args9.columns) || "", _this12.type), ..._this12.extractNestings(((_args10 = args) == null ? void 0 : _args10.sort) || "", _this12.type)]; // Decide which aliases we can join: only when map.type===MODEL AND reference is a STRING keyspace.
|
|
1324
1328
|
|
|
1325
1329
|
var mappedNestings = _.compact(_.uniq(nestings).map(alias => {
|
|
1326
1330
|
var prop = _this12.props[alias];
|
|
@@ -1417,11 +1421,11 @@ class SpiceModel {
|
|
|
1417
1421
|
|
|
1418
1422
|
try {
|
|
1419
1423
|
if (p) {
|
|
1420
|
-
var
|
|
1424
|
+
var _args11, _args12;
|
|
1421
1425
|
|
|
1422
1426
|
return yield p.track(_this12.type + ".list", doList, {
|
|
1423
|
-
limit: (
|
|
1424
|
-
offset: (
|
|
1427
|
+
limit: (_args11 = args) == null ? void 0 : _args11.limit,
|
|
1428
|
+
offset: (_args12 = args) == null ? void 0 : _args12.offset
|
|
1425
1429
|
});
|
|
1426
1430
|
}
|
|
1427
1431
|
|
|
@@ -1589,9 +1593,9 @@ class SpiceModel {
|
|
|
1589
1593
|
data = Array.of(data);
|
|
1590
1594
|
}
|
|
1591
1595
|
|
|
1592
|
-
_this15[
|
|
1596
|
+
var isExempt = _this15[_mapping_dept_exempt].includes(source_property);
|
|
1593
1597
|
|
|
1594
|
-
if (_this15[_level] + 1 < _this15[_mapping_dept]) {
|
|
1598
|
+
if (isExempt || _this15[_level] + 1 < _this15[_mapping_dept]) {
|
|
1595
1599
|
var classes = _.compact(_.isArray(Class) ? Class : [Class]);
|
|
1596
1600
|
|
|
1597
1601
|
var ids = [];
|
|
@@ -1606,7 +1610,8 @@ class SpiceModel {
|
|
|
1606
1610
|
return new obj(_extends({}, _this15[_args], {
|
|
1607
1611
|
skip_cache: _this15[_skip_cache],
|
|
1608
1612
|
_level: _this15[_level] + 1,
|
|
1609
|
-
mapping_dept: _this15[_mapping_dept]
|
|
1613
|
+
mapping_dept: _this15[_mapping_dept],
|
|
1614
|
+
mapping_dept_exempt: _this15[_mapping_dept_exempt]
|
|
1610
1615
|
})).getMulti({
|
|
1611
1616
|
skip_hooks: true,
|
|
1612
1617
|
ids: ids
|
|
@@ -1640,7 +1645,9 @@ class SpiceModel {
|
|
|
1640
1645
|
data = Array.of(data);
|
|
1641
1646
|
}
|
|
1642
1647
|
|
|
1643
|
-
|
|
1648
|
+
var isExempt = _this16[_mapping_dept_exempt].includes(source_property);
|
|
1649
|
+
|
|
1650
|
+
if (isExempt || _this16[_level] + 1 < _this16[_mapping_dept]) {
|
|
1644
1651
|
var ids = [];
|
|
1645
1652
|
|
|
1646
1653
|
_.each(data, result => {
|
|
@@ -1665,7 +1672,8 @@ class SpiceModel {
|
|
|
1665
1672
|
return new obj(_extends({}, _this16[_args], {
|
|
1666
1673
|
skip_cache: _this16[_skip_cache],
|
|
1667
1674
|
_level: _this16[_level] + 1,
|
|
1668
|
-
mapping_dept: _this16[_mapping_dept]
|
|
1675
|
+
mapping_dept: _this16[_mapping_dept],
|
|
1676
|
+
mapping_dept_exempt: _this16[_mapping_dept_exempt]
|
|
1669
1677
|
})).getMulti({
|
|
1670
1678
|
skip_hooks: true,
|
|
1671
1679
|
ids: ids
|
|
@@ -1870,21 +1878,84 @@ class SpiceModel {
|
|
|
1870
1878
|
var requestedColumns = _this18.parseRequestedColumns(args == null ? void 0 : args.columns); // Cache the modifiers lookup for the specified type.
|
|
1871
1879
|
|
|
1872
1880
|
|
|
1873
|
-
var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || [];
|
|
1881
|
+
var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || []; // ⚡ OPTIMIZED: Separate field-specific modifiers (can run in parallel) from generic ones (serial)
|
|
1882
|
+
|
|
1883
|
+
var fieldModifiers = [];
|
|
1884
|
+
var genericModifiers = [];
|
|
1874
1885
|
|
|
1875
1886
|
for (var modifier of modifiers) {
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1887
|
+
// Skip field-specific modifiers if columns specified and field not requested
|
|
1888
|
+
if (requestedColumns && modifier.field && !requestedColumns.has(modifier.field)) {
|
|
1889
|
+
continue;
|
|
1890
|
+
} // Field modifiers have a .field property and .execute function - they can run in parallel
|
|
1891
|
+
|
|
1892
|
+
|
|
1893
|
+
if (modifier.field && typeof modifier.execute === "function") {
|
|
1894
|
+
fieldModifiers.push(modifier);
|
|
1895
|
+
} else {
|
|
1896
|
+
genericModifiers.push(modifier);
|
|
1897
|
+
}
|
|
1898
|
+
} // Run generic modifiers serially first (they may transform the data structure)
|
|
1881
1899
|
|
|
1882
1900
|
|
|
1883
|
-
|
|
1901
|
+
for (var _modifier of genericModifiers) {
|
|
1902
|
+
try {
|
|
1903
|
+
var executeFn = typeof _modifier === "function" ? _modifier : _modifier.execute;
|
|
1884
1904
|
data = yield executeFn(data, old_data, _this18[_ctx], _this18.type);
|
|
1885
1905
|
} catch (error) {
|
|
1886
|
-
console.error("Modifier error in do_serialize:", error.stack);
|
|
1906
|
+
console.error("Modifier error in do_serialize (generic):", error.stack);
|
|
1887
1907
|
}
|
|
1908
|
+
} // ⚡ OPTIMIZED: Run field-specific modifiers in PARALLEL - each populates a different field
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
if (fieldModifiers.length > 0) {
|
|
1912
|
+
var _originalIsArray = Array.isArray(data);
|
|
1913
|
+
|
|
1914
|
+
var dataArray = _originalIsArray ? data : [data]; // Run all field modifiers in parallel
|
|
1915
|
+
|
|
1916
|
+
var fieldResults = yield Promise.allSettled(fieldModifiers.map(
|
|
1917
|
+
/*#__PURE__*/
|
|
1918
|
+
function () {
|
|
1919
|
+
var _ref17 = _asyncToGenerator(function* (modifier) {
|
|
1920
|
+
try {
|
|
1921
|
+
// Each modifier gets a copy of data and returns its field mappings
|
|
1922
|
+
var result = yield modifier.execute(_originalIsArray ? [...dataArray] : dataArray[0], old_data, _this18[_ctx], _this18.type);
|
|
1923
|
+
return {
|
|
1924
|
+
field: modifier.field,
|
|
1925
|
+
result
|
|
1926
|
+
};
|
|
1927
|
+
} catch (error) {
|
|
1928
|
+
console.error("Modifier error for field " + modifier.field + ":", error.stack);
|
|
1929
|
+
return {
|
|
1930
|
+
field: modifier.field,
|
|
1931
|
+
result: null,
|
|
1932
|
+
error
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
});
|
|
1936
|
+
|
|
1937
|
+
return function (_x3) {
|
|
1938
|
+
return _ref17.apply(this, arguments);
|
|
1939
|
+
};
|
|
1940
|
+
}())); // Merge results - each field modifier added its field to the data items
|
|
1941
|
+
|
|
1942
|
+
for (var outcome of fieldResults) {
|
|
1943
|
+
if (outcome.status === "fulfilled" && outcome.value.result) {
|
|
1944
|
+
var {
|
|
1945
|
+
field,
|
|
1946
|
+
result
|
|
1947
|
+
} = outcome.value;
|
|
1948
|
+
var resultArray = Array.isArray(result) ? result : [result]; // Copy the mapped field from each result item to the corresponding data item
|
|
1949
|
+
|
|
1950
|
+
for (var i = 0; i < dataArray.length && i < resultArray.length; i++) {
|
|
1951
|
+
if (resultArray[i] && resultArray[i][field] !== undefined) {
|
|
1952
|
+
dataArray[i][field] = resultArray[i][field];
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
data = _originalIsArray ? dataArray : dataArray[0];
|
|
1888
1959
|
} // Ensure data is always an array for consistent processing.
|
|
1889
1960
|
|
|
1890
1961
|
|
package/package.json
CHANGED
package/src/models/SpiceModel.js
CHANGED
|
@@ -20,7 +20,8 @@ var SDate = require("sonover-date"),
|
|
|
20
20
|
_skip_cache = Symbol(),
|
|
21
21
|
_serializers = Symbol(),
|
|
22
22
|
_level = Symbol(),
|
|
23
|
-
_mapping_dept = Symbol()
|
|
23
|
+
_mapping_dept = Symbol(),
|
|
24
|
+
_mapping_dept_exempt = Symbol();
|
|
24
25
|
|
|
25
26
|
//const _type = Symbol("type");
|
|
26
27
|
|
|
@@ -52,6 +53,7 @@ export default class SpiceModel {
|
|
|
52
53
|
spice.config.database.connections[args.connection].type || "couchbase";
|
|
53
54
|
let Database = require(`spice-${dbtype}`);
|
|
54
55
|
this[_mapping_dept] = args?.args?.mapping_dept || 100;
|
|
56
|
+
this[_mapping_dept_exempt] = args?.args?.mapping_dept_exempt || [];
|
|
55
57
|
this.type = "";
|
|
56
58
|
this.collection = args.connection;
|
|
57
59
|
this[_args] = args.args;
|
|
@@ -491,6 +493,8 @@ export default class SpiceModel {
|
|
|
491
493
|
|
|
492
494
|
const doGet = async () => {
|
|
493
495
|
if (args.mapping_dept) this[_mapping_dept] = args.mapping_dept;
|
|
496
|
+
if (args.mapping_dept_exempt)
|
|
497
|
+
this[_mapping_dept_exempt] = args.mapping_dept_exempt;
|
|
494
498
|
|
|
495
499
|
if (!args) {
|
|
496
500
|
args = {};
|
|
@@ -563,12 +567,12 @@ export default class SpiceModel {
|
|
|
563
567
|
await this.propsToBeRemoved(results)
|
|
564
568
|
);
|
|
565
569
|
}
|
|
566
|
-
|
|
570
|
+
|
|
567
571
|
// ⚡ OPTIMIZED: Filter results by columns if specified
|
|
568
572
|
if (args.columns) {
|
|
569
573
|
results = this.filterResultsByColumns([results], args.columns)[0];
|
|
570
574
|
}
|
|
571
|
-
|
|
575
|
+
|
|
572
576
|
if (args.skip_hooks !== true) {
|
|
573
577
|
await this.run_hook(results, "get", "after");
|
|
574
578
|
}
|
|
@@ -1144,6 +1148,8 @@ export default class SpiceModel {
|
|
|
1144
1148
|
|
|
1145
1149
|
const doList = async () => {
|
|
1146
1150
|
if (args.mapping_dept) this[_mapping_dept] = args.mapping_dept;
|
|
1151
|
+
if (args.mapping_dept_exempt)
|
|
1152
|
+
this[_mapping_dept_exempt] = args.mapping_dept_exempt;
|
|
1147
1153
|
|
|
1148
1154
|
// Find alias tokens from query/columns/sort
|
|
1149
1155
|
const nestings = [
|
|
@@ -1417,9 +1423,8 @@ export default class SpiceModel {
|
|
|
1417
1423
|
if (!original_is_array) {
|
|
1418
1424
|
data = Array.of(data);
|
|
1419
1425
|
}
|
|
1420
|
-
this[
|
|
1421
|
-
|
|
1422
|
-
if (this[_level] + 1 < this[_mapping_dept]) {
|
|
1426
|
+
const isExempt = this[_mapping_dept_exempt].includes(source_property);
|
|
1427
|
+
if (isExempt || this[_level] + 1 < this[_mapping_dept]) {
|
|
1423
1428
|
let classes = _.compact(_.isArray(Class) ? Class : [Class]);
|
|
1424
1429
|
|
|
1425
1430
|
let ids = [];
|
|
@@ -1439,6 +1444,7 @@ export default class SpiceModel {
|
|
|
1439
1444
|
skip_cache: this[_skip_cache],
|
|
1440
1445
|
_level: this[_level] + 1,
|
|
1441
1446
|
mapping_dept: this[_mapping_dept],
|
|
1447
|
+
mapping_dept_exempt: this[_mapping_dept_exempt],
|
|
1442
1448
|
}).getMulti({
|
|
1443
1449
|
skip_hooks: true,
|
|
1444
1450
|
ids: ids,
|
|
@@ -1476,7 +1482,8 @@ export default class SpiceModel {
|
|
|
1476
1482
|
if (!original_is_array) {
|
|
1477
1483
|
data = Array.of(data);
|
|
1478
1484
|
}
|
|
1479
|
-
|
|
1485
|
+
const isExempt = this[_mapping_dept_exempt].includes(source_property);
|
|
1486
|
+
if (isExempt || this[_level] + 1 < this[_mapping_dept]) {
|
|
1480
1487
|
let ids = [];
|
|
1481
1488
|
_.each(data, (result) => {
|
|
1482
1489
|
let value = [];
|
|
@@ -1501,6 +1508,7 @@ export default class SpiceModel {
|
|
|
1501
1508
|
skip_cache: this[_skip_cache],
|
|
1502
1509
|
_level: this[_level] + 1,
|
|
1503
1510
|
mapping_dept: this[_mapping_dept],
|
|
1511
|
+
mapping_dept_exempt: this[_mapping_dept_exempt],
|
|
1504
1512
|
}).getMulti({
|
|
1505
1513
|
skip_hooks: true,
|
|
1506
1514
|
ids: ids,
|
|
@@ -1619,12 +1627,12 @@ export default class SpiceModel {
|
|
|
1619
1627
|
// ⚡ Parse columns string into a Set for fast lookup
|
|
1620
1628
|
parseRequestedColumns(columns) {
|
|
1621
1629
|
if (!columns || columns === "") return null;
|
|
1622
|
-
|
|
1630
|
+
|
|
1623
1631
|
// Extract field names from column specifications
|
|
1624
1632
|
// Handles: "field", "`field`", "table.field", "`table`.`field`", "expr AS alias"
|
|
1625
1633
|
const fields = new Set();
|
|
1626
1634
|
const columnList = columns.split(",").map((c) => c.trim());
|
|
1627
|
-
|
|
1635
|
+
|
|
1628
1636
|
for (const col of columnList) {
|
|
1629
1637
|
// Check for AS alias
|
|
1630
1638
|
const aliasMatch = col.match(/\s+AS\s+`?([\w]+)`?$/i);
|
|
@@ -1632,7 +1640,7 @@ export default class SpiceModel {
|
|
|
1632
1640
|
fields.add(aliasMatch[1]);
|
|
1633
1641
|
continue;
|
|
1634
1642
|
}
|
|
1635
|
-
|
|
1643
|
+
|
|
1636
1644
|
// Get the last part after dots (the field name)
|
|
1637
1645
|
const parts = col.replace(/`/g, "").split(".");
|
|
1638
1646
|
const fieldName = parts[parts.length - 1];
|
|
@@ -1640,7 +1648,7 @@ export default class SpiceModel {
|
|
|
1640
1648
|
fields.add(fieldName);
|
|
1641
1649
|
}
|
|
1642
1650
|
}
|
|
1643
|
-
|
|
1651
|
+
|
|
1644
1652
|
return fields.size > 0 ? fields : null;
|
|
1645
1653
|
}
|
|
1646
1654
|
|
|
@@ -1665,21 +1673,92 @@ export default class SpiceModel {
|
|
|
1665
1673
|
|
|
1666
1674
|
// Cache the modifiers lookup for the specified type.
|
|
1667
1675
|
const modifiers = this[_serializers]?.[type]?.modifiers || [];
|
|
1676
|
+
|
|
1677
|
+
// ⚡ OPTIMIZED: Separate field-specific modifiers (can run in parallel) from generic ones (serial)
|
|
1678
|
+
const fieldModifiers = [];
|
|
1679
|
+
const genericModifiers = [];
|
|
1680
|
+
|
|
1668
1681
|
for (const modifier of modifiers) {
|
|
1682
|
+
// Skip field-specific modifiers if columns specified and field not requested
|
|
1683
|
+
if (
|
|
1684
|
+
requestedColumns &&
|
|
1685
|
+
modifier.field &&
|
|
1686
|
+
!requestedColumns.has(modifier.field)
|
|
1687
|
+
) {
|
|
1688
|
+
continue;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// Field modifiers have a .field property and .execute function - they can run in parallel
|
|
1692
|
+
if (modifier.field && typeof modifier.execute === "function") {
|
|
1693
|
+
fieldModifiers.push(modifier);
|
|
1694
|
+
} else {
|
|
1695
|
+
genericModifiers.push(modifier);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
// Run generic modifiers serially first (they may transform the data structure)
|
|
1700
|
+
for (const modifier of genericModifiers) {
|
|
1669
1701
|
try {
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
continue; // Skip this modifier - field not in requested columns
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
// Execute modifier (supports both old function format and new object format)
|
|
1676
|
-
const executeFn = typeof modifier === "function" ? modifier : modifier.execute;
|
|
1702
|
+
const executeFn =
|
|
1703
|
+
typeof modifier === "function" ? modifier : modifier.execute;
|
|
1677
1704
|
data = await executeFn(data, old_data, this[_ctx], this.type);
|
|
1678
1705
|
} catch (error) {
|
|
1679
|
-
console.error(
|
|
1706
|
+
console.error(
|
|
1707
|
+
"Modifier error in do_serialize (generic):",
|
|
1708
|
+
error.stack
|
|
1709
|
+
);
|
|
1680
1710
|
}
|
|
1681
1711
|
}
|
|
1682
1712
|
|
|
1713
|
+
// ⚡ OPTIMIZED: Run field-specific modifiers in PARALLEL - each populates a different field
|
|
1714
|
+
if (fieldModifiers.length > 0) {
|
|
1715
|
+
const originalIsArray = Array.isArray(data);
|
|
1716
|
+
const dataArray = originalIsArray ? data : [data];
|
|
1717
|
+
|
|
1718
|
+
// Run all field modifiers in parallel
|
|
1719
|
+
const fieldResults = await Promise.allSettled(
|
|
1720
|
+
fieldModifiers.map(async (modifier) => {
|
|
1721
|
+
try {
|
|
1722
|
+
// Each modifier gets a copy of data and returns its field mappings
|
|
1723
|
+
const result = await modifier.execute(
|
|
1724
|
+
originalIsArray ? [...dataArray] : dataArray[0],
|
|
1725
|
+
old_data,
|
|
1726
|
+
this[_ctx],
|
|
1727
|
+
this.type
|
|
1728
|
+
);
|
|
1729
|
+
return { field: modifier.field, result };
|
|
1730
|
+
} catch (error) {
|
|
1731
|
+
console.error(
|
|
1732
|
+
`Modifier error for field ${modifier.field}:`,
|
|
1733
|
+
error.stack
|
|
1734
|
+
);
|
|
1735
|
+
return { field: modifier.field, result: null, error };
|
|
1736
|
+
}
|
|
1737
|
+
})
|
|
1738
|
+
);
|
|
1739
|
+
|
|
1740
|
+
// Merge results - each field modifier added its field to the data items
|
|
1741
|
+
for (const outcome of fieldResults) {
|
|
1742
|
+
if (outcome.status === "fulfilled" && outcome.value.result) {
|
|
1743
|
+
const { field, result } = outcome.value;
|
|
1744
|
+
const resultArray = Array.isArray(result) ? result : [result];
|
|
1745
|
+
|
|
1746
|
+
// Copy the mapped field from each result item to the corresponding data item
|
|
1747
|
+
for (
|
|
1748
|
+
let i = 0;
|
|
1749
|
+
i < dataArray.length && i < resultArray.length;
|
|
1750
|
+
i++
|
|
1751
|
+
) {
|
|
1752
|
+
if (resultArray[i] && resultArray[i][field] !== undefined) {
|
|
1753
|
+
dataArray[i][field] = resultArray[i][field];
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
data = originalIsArray ? dataArray : dataArray[0];
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1683
1762
|
// Ensure data is always an array for consistent processing.
|
|
1684
1763
|
const originalIsArray = Array.isArray(data);
|
|
1685
1764
|
if (!originalIsArray) {
|