spice-js 2.7.3 → 2.7.4
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 +30 -157
- package/package.json +1 -1
- package/src/models/SpiceModel.js +22 -137
|
@@ -54,7 +54,6 @@ if (!Promise.allSettled) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
class SpiceModel {
|
|
57
|
-
// ⚡ Static caches for performance optimization
|
|
58
57
|
constructor(args) {
|
|
59
58
|
if (args === void 0) {
|
|
60
59
|
args = {};
|
|
@@ -1559,54 +1558,6 @@ class SpiceModel {
|
|
|
1559
1558
|
}
|
|
1560
1559
|
|
|
1561
1560
|
return true;
|
|
1562
|
-
} // ⚡ OPTIMIZED: Cache defaults metadata per model type
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
getDefaultsMetadata(type) {
|
|
1566
|
-
var cacheKey = this.type + "::" + type;
|
|
1567
|
-
|
|
1568
|
-
if (!SpiceModel._defaultsCache[cacheKey]) {
|
|
1569
|
-
var staticDefaults = {};
|
|
1570
|
-
var dynamicDefaults = []; // Pre-compute once per model type
|
|
1571
|
-
|
|
1572
|
-
for (var key in this.props) {
|
|
1573
|
-
var _this$props$key, _this$props$key$defau;
|
|
1574
|
-
|
|
1575
|
-
var def = (_this$props$key = this.props[key]) == null ? void 0 : (_this$props$key$defau = _this$props$key.defaults) == null ? void 0 : _this$props$key$defau[type];
|
|
1576
|
-
|
|
1577
|
-
if (def !== undefined) {
|
|
1578
|
-
if (_.isFunction(def)) {
|
|
1579
|
-
dynamicDefaults.push({
|
|
1580
|
-
key,
|
|
1581
|
-
fn: def
|
|
1582
|
-
});
|
|
1583
|
-
} else {
|
|
1584
|
-
staticDefaults[key] = def;
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
SpiceModel._defaultsCache[cacheKey] = {
|
|
1590
|
-
staticDefaults,
|
|
1591
|
-
dynamicDefaults,
|
|
1592
|
-
hasDefaults: Object.keys(staticDefaults).length > 0 || dynamicDefaults.length > 0
|
|
1593
|
-
};
|
|
1594
|
-
}
|
|
1595
|
-
|
|
1596
|
-
return SpiceModel._defaultsCache[cacheKey];
|
|
1597
|
-
} // ⚡ OPTIMIZED: Cache hidden props per model type
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
getHiddenProps() {
|
|
1601
|
-
if (!SpiceModel._hiddenPropsCache[this.type]) {
|
|
1602
|
-
SpiceModel._hiddenPropsCache[this.type] = Object.keys(this.props).filter(key => {
|
|
1603
|
-
var _this$props$key2;
|
|
1604
|
-
|
|
1605
|
-
return (_this$props$key2 = this.props[key]) == null ? void 0 : _this$props$key2.hide;
|
|
1606
|
-
});
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
return SpiceModel._hiddenPropsCache[this.type];
|
|
1610
1561
|
} // Check if a field is exempt from mapping depth limits
|
|
1611
1562
|
// Supports deep references like "group.permissions"
|
|
1612
1563
|
|
|
@@ -1816,18 +1767,11 @@ class SpiceModel {
|
|
|
1816
1767
|
addModifier(_ref18) {
|
|
1817
1768
|
var {
|
|
1818
1769
|
when,
|
|
1819
|
-
execute
|
|
1820
|
-
field = null,
|
|
1821
|
-
sourceField = null
|
|
1770
|
+
execute
|
|
1822
1771
|
} = _ref18;
|
|
1823
1772
|
|
|
1824
1773
|
if (this[_serializers][when]) {
|
|
1825
|
-
|
|
1826
|
-
this[_serializers][when]["modifiers"].push({
|
|
1827
|
-
execute,
|
|
1828
|
-
field,
|
|
1829
|
-
sourceField
|
|
1830
|
-
});
|
|
1774
|
+
this[_serializers][when]["modifiers"].push(execute);
|
|
1831
1775
|
}
|
|
1832
1776
|
}
|
|
1833
1777
|
|
|
@@ -1856,21 +1800,15 @@ class SpiceModel {
|
|
|
1856
1800
|
switch (properties[i].map.type) {
|
|
1857
1801
|
case _2.MapType.MODEL:
|
|
1858
1802
|
{
|
|
1859
|
-
var destinationField = properties[i].map.destination || i;
|
|
1860
|
-
|
|
1861
1803
|
switch (properties[i].type) {
|
|
1862
1804
|
case String:
|
|
1863
1805
|
case "string":
|
|
1864
1806
|
{
|
|
1865
1807
|
_this17.addModifier({
|
|
1866
1808
|
when: properties[i].map.when || "read",
|
|
1867
|
-
field: destinationField,
|
|
1868
|
-
// ⚡ Track which field this modifier populates
|
|
1869
|
-
sourceField: i,
|
|
1870
|
-
// ⚡ Track source property for column filtering
|
|
1871
1809
|
execute: function () {
|
|
1872
1810
|
var _execute = _asyncToGenerator(function* (data) {
|
|
1873
|
-
return yield _this17.mapToObject(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i,
|
|
1811
|
+
return yield _this17.mapToObject(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i, properties[i].map.destination || i, properties[i]);
|
|
1874
1812
|
});
|
|
1875
1813
|
|
|
1876
1814
|
function execute(_x) {
|
|
@@ -1889,13 +1827,9 @@ class SpiceModel {
|
|
|
1889
1827
|
{
|
|
1890
1828
|
_this17.addModifier({
|
|
1891
1829
|
when: properties[i].map.when || "read",
|
|
1892
|
-
field: destinationField,
|
|
1893
|
-
// ⚡ Track which field this modifier populates
|
|
1894
|
-
sourceField: i,
|
|
1895
|
-
// ⚡ Track source property for column filtering
|
|
1896
1830
|
execute: function () {
|
|
1897
1831
|
var _execute2 = _asyncToGenerator(function* (data) {
|
|
1898
|
-
return yield _this17.mapToObjectArray(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i,
|
|
1832
|
+
return yield _this17.mapToObjectArray(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i, properties[i].map.destination || i, properties[i]);
|
|
1899
1833
|
});
|
|
1900
1834
|
|
|
1901
1835
|
function execute(_x2) {
|
|
@@ -1924,42 +1858,6 @@ class SpiceModel {
|
|
|
1924
1858
|
for (var i in properties) {
|
|
1925
1859
|
_loop(i);
|
|
1926
1860
|
}
|
|
1927
|
-
} // ⚡ Parse columns string into a Set for fast lookup
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
parseRequestedColumns(columns) {
|
|
1931
|
-
if (!columns || columns === "") return null; // Handle array of columns (convert to string)
|
|
1932
|
-
|
|
1933
|
-
if (Array.isArray(columns)) {
|
|
1934
|
-
columns = columns.join(",");
|
|
1935
|
-
} // Must be a string to parse
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
if (typeof columns !== "string") return null; // Extract field names from column specifications
|
|
1939
|
-
// Handles: "field", "`field`", "table.field", "`table`.`field`", "expr AS alias"
|
|
1940
|
-
|
|
1941
|
-
var fields = new Set();
|
|
1942
|
-
var columnList = columns.split(",").map(c => c.trim());
|
|
1943
|
-
|
|
1944
|
-
for (var col of columnList) {
|
|
1945
|
-
// Check for AS alias
|
|
1946
|
-
var aliasMatch = col.match(/\s+AS\s+`?([\w]+)`?$/i);
|
|
1947
|
-
|
|
1948
|
-
if (aliasMatch) {
|
|
1949
|
-
fields.add(aliasMatch[1]);
|
|
1950
|
-
continue;
|
|
1951
|
-
} // Get the last part after dots (the field name)
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
var parts = col.replace(/`/g, "").split(".");
|
|
1955
|
-
var fieldName = parts[parts.length - 1];
|
|
1956
|
-
|
|
1957
|
-
if (fieldName && fieldName !== "*") {
|
|
1958
|
-
fields.add(fieldName);
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
return fields.size > 0 ? fields : null;
|
|
1963
1861
|
}
|
|
1964
1862
|
|
|
1965
1863
|
do_serialize(data, type, old_data, args, path_to_be_removed) {
|
|
@@ -1991,28 +1889,14 @@ class SpiceModel {
|
|
|
1991
1889
|
_this18.addExternalModifiers(_this18.type);
|
|
1992
1890
|
|
|
1993
1891
|
_this18[_external_modifier_loaded] = true;
|
|
1994
|
-
} //
|
|
1995
|
-
|
|
1892
|
+
} // Cache the modifiers lookup for the specified type.
|
|
1996
1893
|
|
|
1997
|
-
var requestedColumns = _this18.parseRequestedColumns(args == null ? void 0 : args.columns); // Cache the modifiers lookup for the specified type.
|
|
1998
1894
|
|
|
1999
|
-
|
|
2000
|
-
var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || []; // Run modifiers serially
|
|
1895
|
+
var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || [];
|
|
2001
1896
|
|
|
2002
1897
|
for (var modifier of modifiers) {
|
|
2003
|
-
// Skip field-specific modifiers if columns specified and field is not requested
|
|
2004
|
-
if (requestedColumns && modifier.field && !requestedColumns.has(modifier.field) && !(modifier.sourceField && requestedColumns.has(modifier.sourceField))) {
|
|
2005
|
-
continue;
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2008
1898
|
try {
|
|
2009
|
-
|
|
2010
|
-
var executeFn = typeof modifier === "function" ? modifier : modifier.execute;
|
|
2011
|
-
var result = yield executeFn(data, old_data, _this18[_ctx], _this18.type); // Only assign if modifier returned a value to prevent data corruption
|
|
2012
|
-
|
|
2013
|
-
if (result !== undefined) {
|
|
2014
|
-
data = result;
|
|
2015
|
-
}
|
|
1899
|
+
data = yield modifier(data, old_data, _this18[_ctx], _this18.type);
|
|
2016
1900
|
} catch (error) {
|
|
2017
1901
|
console.error("Modifier error in do_serialize:", error.stack);
|
|
2018
1902
|
}
|
|
@@ -2023,42 +1907,33 @@ class SpiceModel {
|
|
|
2023
1907
|
|
|
2024
1908
|
if (!originalIsArray) {
|
|
2025
1909
|
data = [data];
|
|
2026
|
-
} //
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
var {
|
|
2030
|
-
staticDefaults,
|
|
2031
|
-
dynamicDefaults,
|
|
2032
|
-
hasDefaults
|
|
2033
|
-
} = _this18.getDefaultsMetadata(type);
|
|
2034
|
-
|
|
2035
|
-
if (hasDefaults) {
|
|
2036
|
-
data = data.map(item => {
|
|
2037
|
-
// Apply static defaults first (fast - no function calls)
|
|
2038
|
-
var result = _.defaults({}, item, staticDefaults); // Only compute dynamic defaults if there are any
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
for (var {
|
|
2042
|
-
key,
|
|
2043
|
-
fn
|
|
2044
|
-
} of dynamicDefaults) {
|
|
2045
|
-
if (result[key] === undefined) {
|
|
2046
|
-
result[key] = fn({
|
|
2047
|
-
old_data: data,
|
|
2048
|
-
new_data: old_data
|
|
2049
|
-
});
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
1910
|
+
} // Compute the defaults from properties using reduce.
|
|
2052
1911
|
|
|
2053
|
-
return result;
|
|
2054
|
-
});
|
|
2055
|
-
} // If type is "read", clean the data by omitting certain props.
|
|
2056
1912
|
|
|
1913
|
+
var defaults = Object.keys(_this18.props).reduce((acc, key) => {
|
|
1914
|
+
var _this18$props$key, _this18$props$key$def;
|
|
1915
|
+
|
|
1916
|
+
var def = (_this18$props$key = _this18.props[key]) == null ? void 0 : (_this18$props$key$def = _this18$props$key.defaults) == null ? void 0 : _this18$props$key$def[type];
|
|
1917
|
+
|
|
1918
|
+
if (def !== undefined) {
|
|
1919
|
+
acc[key] = _.isFunction(def) ? def({
|
|
1920
|
+
old_data: data,
|
|
1921
|
+
new_data: old_data
|
|
1922
|
+
}) : def;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
return acc;
|
|
1926
|
+
}, {}); // Merge defaults into each object.
|
|
1927
|
+
|
|
1928
|
+
data = data.map(item => _.defaults(item, defaults)); // If type is "read", clean the data by omitting certain props.
|
|
2057
1929
|
|
|
2058
1930
|
if (type === "read") {
|
|
2059
|
-
//
|
|
2060
|
-
var hiddenProps = _this18.
|
|
1931
|
+
// Collect hidden properties from schema.
|
|
1932
|
+
var hiddenProps = Object.keys(_this18.props).filter(key => {
|
|
1933
|
+
var _this18$props$key2;
|
|
2061
1934
|
|
|
1935
|
+
return (_this18$props$key2 = _this18.props[key]) == null ? void 0 : _this18$props$key2.hide;
|
|
1936
|
+
}); // Combine default props to remove.
|
|
2062
1937
|
|
|
2063
1938
|
var propsToClean = ["deleted", "type", ...path_to_be_removed, ...hiddenProps];
|
|
2064
1939
|
data = data.map(item => _.omit(item, propsToClean));
|
|
@@ -2090,6 +1965,4 @@ class SpiceModel {
|
|
|
2090
1965
|
|
|
2091
1966
|
}
|
|
2092
1967
|
|
|
2093
|
-
exports.default = SpiceModel;
|
|
2094
|
-
SpiceModel._defaultsCache = {};
|
|
2095
|
-
SpiceModel._hiddenPropsCache = {};
|
|
1968
|
+
exports.default = SpiceModel;
|
package/package.json
CHANGED
package/src/models/SpiceModel.js
CHANGED
|
@@ -44,10 +44,6 @@ if (!Promise.allSettled) {
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
export default class SpiceModel {
|
|
47
|
-
// ⚡ Static caches for performance optimization
|
|
48
|
-
static _defaultsCache = {};
|
|
49
|
-
static _hiddenPropsCache = {};
|
|
50
|
-
|
|
51
47
|
constructor(args = {}) {
|
|
52
48
|
try {
|
|
53
49
|
var dbtype =
|
|
@@ -1391,47 +1387,6 @@ export default class SpiceModel {
|
|
|
1391
1387
|
return true;
|
|
1392
1388
|
}
|
|
1393
1389
|
|
|
1394
|
-
// ⚡ OPTIMIZED: Cache defaults metadata per model type
|
|
1395
|
-
getDefaultsMetadata(type) {
|
|
1396
|
-
const cacheKey = `${this.type}::${type}`;
|
|
1397
|
-
|
|
1398
|
-
if (!SpiceModel._defaultsCache[cacheKey]) {
|
|
1399
|
-
const staticDefaults = {};
|
|
1400
|
-
const dynamicDefaults = [];
|
|
1401
|
-
|
|
1402
|
-
// Pre-compute once per model type
|
|
1403
|
-
for (const key in this.props) {
|
|
1404
|
-
const def = this.props[key]?.defaults?.[type];
|
|
1405
|
-
if (def !== undefined) {
|
|
1406
|
-
if (_.isFunction(def)) {
|
|
1407
|
-
dynamicDefaults.push({ key, fn: def });
|
|
1408
|
-
} else {
|
|
1409
|
-
staticDefaults[key] = def;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
SpiceModel._defaultsCache[cacheKey] = {
|
|
1415
|
-
staticDefaults,
|
|
1416
|
-
dynamicDefaults,
|
|
1417
|
-
hasDefaults:
|
|
1418
|
-
Object.keys(staticDefaults).length > 0 || dynamicDefaults.length > 0,
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
return SpiceModel._defaultsCache[cacheKey];
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
// ⚡ OPTIMIZED: Cache hidden props per model type
|
|
1426
|
-
getHiddenProps() {
|
|
1427
|
-
if (!SpiceModel._hiddenPropsCache[this.type]) {
|
|
1428
|
-
SpiceModel._hiddenPropsCache[this.type] = Object.keys(this.props).filter(
|
|
1429
|
-
(key) => this.props[key]?.hide
|
|
1430
|
-
);
|
|
1431
|
-
}
|
|
1432
|
-
return SpiceModel._hiddenPropsCache[this.type];
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
1390
|
// Check if a field is exempt from mapping depth limits
|
|
1436
1391
|
// Supports deep references like "group.permissions"
|
|
1437
1392
|
isFieldExempt(source_property) {
|
|
@@ -1634,14 +1589,9 @@ export default class SpiceModel {
|
|
|
1634
1589
|
return original_is_array ? data : data[0];
|
|
1635
1590
|
}
|
|
1636
1591
|
|
|
1637
|
-
addModifier({ when, execute
|
|
1592
|
+
addModifier({ when, execute }) {
|
|
1638
1593
|
if (this[_serializers][when]) {
|
|
1639
|
-
|
|
1640
|
-
this[_serializers][when]["modifiers"].push({
|
|
1641
|
-
execute,
|
|
1642
|
-
field,
|
|
1643
|
-
sourceField,
|
|
1644
|
-
});
|
|
1594
|
+
this[_serializers][when]["modifiers"].push(execute);
|
|
1645
1595
|
}
|
|
1646
1596
|
}
|
|
1647
1597
|
|
|
@@ -1662,14 +1612,11 @@ export default class SpiceModel {
|
|
|
1662
1612
|
if (properties[i].map) {
|
|
1663
1613
|
switch (properties[i].map.type) {
|
|
1664
1614
|
case MapType.MODEL: {
|
|
1665
|
-
const destinationField = properties[i].map.destination || i;
|
|
1666
1615
|
switch (properties[i].type) {
|
|
1667
1616
|
case String:
|
|
1668
1617
|
case "string": {
|
|
1669
1618
|
this.addModifier({
|
|
1670
1619
|
when: properties[i].map.when || "read",
|
|
1671
|
-
field: destinationField, // ⚡ Track which field this modifier populates
|
|
1672
|
-
sourceField: i, // ⚡ Track source property for column filtering
|
|
1673
1620
|
execute: async (data) => {
|
|
1674
1621
|
return await this.mapToObject(
|
|
1675
1622
|
data,
|
|
@@ -1677,7 +1624,7 @@ export default class SpiceModel {
|
|
|
1677
1624
|
spice.models[properties[i].map.reference]
|
|
1678
1625
|
: properties[i].map.reference,
|
|
1679
1626
|
i,
|
|
1680
|
-
|
|
1627
|
+
properties[i].map.destination || i,
|
|
1681
1628
|
properties[i]
|
|
1682
1629
|
);
|
|
1683
1630
|
},
|
|
@@ -1688,8 +1635,6 @@ export default class SpiceModel {
|
|
|
1688
1635
|
case "array": {
|
|
1689
1636
|
this.addModifier({
|
|
1690
1637
|
when: properties[i].map.when || "read",
|
|
1691
|
-
field: destinationField, // ⚡ Track which field this modifier populates
|
|
1692
|
-
sourceField: i, // ⚡ Track source property for column filtering
|
|
1693
1638
|
execute: async (data) => {
|
|
1694
1639
|
return await this.mapToObjectArray(
|
|
1695
1640
|
data,
|
|
@@ -1697,7 +1642,7 @@ export default class SpiceModel {
|
|
|
1697
1642
|
spice.models[properties[i].map.reference]
|
|
1698
1643
|
: properties[i].map.reference,
|
|
1699
1644
|
i,
|
|
1700
|
-
|
|
1645
|
+
properties[i].map.destination || i,
|
|
1701
1646
|
properties[i]
|
|
1702
1647
|
);
|
|
1703
1648
|
},
|
|
@@ -1715,41 +1660,6 @@ export default class SpiceModel {
|
|
|
1715
1660
|
}
|
|
1716
1661
|
}
|
|
1717
1662
|
|
|
1718
|
-
// ⚡ Parse columns string into a Set for fast lookup
|
|
1719
|
-
parseRequestedColumns(columns) {
|
|
1720
|
-
if (!columns || columns === "") return null;
|
|
1721
|
-
|
|
1722
|
-
// Handle array of columns (convert to string)
|
|
1723
|
-
if (Array.isArray(columns)) {
|
|
1724
|
-
columns = columns.join(",");
|
|
1725
|
-
}
|
|
1726
|
-
|
|
1727
|
-
// Must be a string to parse
|
|
1728
|
-
if (typeof columns !== "string") return null;
|
|
1729
|
-
// Extract field names from column specifications
|
|
1730
|
-
// Handles: "field", "`field`", "table.field", "`table`.`field`", "expr AS alias"
|
|
1731
|
-
const fields = new Set();
|
|
1732
|
-
const columnList = columns.split(",").map((c) => c.trim());
|
|
1733
|
-
|
|
1734
|
-
for (const col of columnList) {
|
|
1735
|
-
// Check for AS alias
|
|
1736
|
-
const aliasMatch = col.match(/\s+AS\s+`?([\w]+)`?$/i);
|
|
1737
|
-
if (aliasMatch) {
|
|
1738
|
-
fields.add(aliasMatch[1]);
|
|
1739
|
-
continue;
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
// Get the last part after dots (the field name)
|
|
1743
|
-
const parts = col.replace(/`/g, "").split(".");
|
|
1744
|
-
const fieldName = parts[parts.length - 1];
|
|
1745
|
-
if (fieldName && fieldName !== "*") {
|
|
1746
|
-
fields.add(fieldName);
|
|
1747
|
-
}
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
return fields.size > 0 ? fields : null;
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
1663
|
async do_serialize(data, type, old_data, args, path_to_be_removed = []) {
|
|
1754
1664
|
// Profiling: use track() for proper async context forking
|
|
1755
1665
|
const p = this[_ctx]?.profiler;
|
|
@@ -1766,33 +1676,11 @@ export default class SpiceModel {
|
|
|
1766
1676
|
this[_external_modifier_loaded] = true;
|
|
1767
1677
|
}
|
|
1768
1678
|
|
|
1769
|
-
// ⚡ OPTIMIZED: Parse requested columns for selective modifier execution
|
|
1770
|
-
const requestedColumns = this.parseRequestedColumns(args?.columns);
|
|
1771
|
-
|
|
1772
1679
|
// Cache the modifiers lookup for the specified type.
|
|
1773
1680
|
const modifiers = this[_serializers]?.[type]?.modifiers || [];
|
|
1774
|
-
|
|
1775
|
-
// Run modifiers serially
|
|
1776
1681
|
for (const modifier of modifiers) {
|
|
1777
|
-
// Skip field-specific modifiers if columns specified and field is not requested
|
|
1778
|
-
if (
|
|
1779
|
-
requestedColumns &&
|
|
1780
|
-
modifier.field &&
|
|
1781
|
-
!requestedColumns.has(modifier.field) &&
|
|
1782
|
-
!(modifier.sourceField && requestedColumns.has(modifier.sourceField))
|
|
1783
|
-
) {
|
|
1784
|
-
continue;
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
1682
|
try {
|
|
1788
|
-
|
|
1789
|
-
const executeFn =
|
|
1790
|
-
typeof modifier === "function" ? modifier : modifier.execute;
|
|
1791
|
-
const result = await executeFn(data, old_data, this[_ctx], this.type);
|
|
1792
|
-
// Only assign if modifier returned a value to prevent data corruption
|
|
1793
|
-
if (result !== undefined) {
|
|
1794
|
-
data = result;
|
|
1795
|
-
}
|
|
1683
|
+
data = await modifier(data, old_data, this[_ctx], this.type);
|
|
1796
1684
|
} catch (error) {
|
|
1797
1685
|
console.error("Modifier error in do_serialize:", error.stack);
|
|
1798
1686
|
}
|
|
@@ -1804,30 +1692,27 @@ export default class SpiceModel {
|
|
|
1804
1692
|
data = [data];
|
|
1805
1693
|
}
|
|
1806
1694
|
|
|
1807
|
-
//
|
|
1808
|
-
const
|
|
1809
|
-
this.
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
if (result[key] === undefined) {
|
|
1819
|
-
result[key] = fn({ old_data: data, new_data: old_data });
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1695
|
+
// Compute the defaults from properties using reduce.
|
|
1696
|
+
const defaults = Object.keys(this.props).reduce((acc, key) => {
|
|
1697
|
+
const def = this.props[key]?.defaults?.[type];
|
|
1698
|
+
if (def !== undefined) {
|
|
1699
|
+
acc[key] =
|
|
1700
|
+
_.isFunction(def) ?
|
|
1701
|
+
def({ old_data: data, new_data: old_data })
|
|
1702
|
+
: def;
|
|
1703
|
+
}
|
|
1704
|
+
return acc;
|
|
1705
|
+
}, {});
|
|
1822
1706
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
}
|
|
1707
|
+
// Merge defaults into each object.
|
|
1708
|
+
data = data.map((item) => _.defaults(item, defaults));
|
|
1826
1709
|
|
|
1827
1710
|
// If type is "read", clean the data by omitting certain props.
|
|
1828
1711
|
if (type === "read") {
|
|
1829
|
-
//
|
|
1830
|
-
const hiddenProps = this.
|
|
1712
|
+
// Collect hidden properties from schema.
|
|
1713
|
+
const hiddenProps = Object.keys(this.props).filter(
|
|
1714
|
+
(key) => this.props[key]?.hide
|
|
1715
|
+
);
|
|
1831
1716
|
// Combine default props to remove.
|
|
1832
1717
|
const propsToClean = [
|
|
1833
1718
|
"deleted",
|