spice-js 2.6.72 → 2.6.74

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.
@@ -566,95 +566,119 @@ class SpiceModel {
566
566
  var _this4 = this;
567
567
 
568
568
  return _asyncToGenerator(function* () {
569
- var _this4$_ctx, _args6;
569
+ var _this4$_ctx;
570
570
 
571
- // Profiling: zero overhead when disabled (single falsy check)
572
- var p = (_this4$_ctx = _this4[_ctx]) == null ? void 0 : _this4$_ctx.profiler,
573
- c = p == null ? void 0 : p.start(_this4.type + ".get", {
574
- id: (_args6 = args) == null ? void 0 : _args6.id
575
- });
571
+ // Profiling: use track() for proper async context forking
572
+ var p = (_this4$_ctx = _this4[_ctx]) == null ? void 0 : _this4$_ctx.profiler;
576
573
 
577
- try {
578
- if (args.mapping_dept) _this4[_mapping_dept] = args.mapping_dept;
574
+ var doGet =
575
+ /*#__PURE__*/
576
+ function () {
577
+ var _ref2 = _asyncToGenerator(function* () {
578
+ if (args.mapping_dept) _this4[_mapping_dept] = args.mapping_dept;
579
579
 
580
- if (!args) {
581
- args = {};
582
- }
583
-
584
- if (_.isString(args.id)) {
585
- if (args.skip_hooks !== true) {
586
- yield _this4.run_hook(args, "get", "before");
580
+ if (!args) {
581
+ args = {};
587
582
  }
588
583
 
589
- var key = "get::" + _this4.type + "::" + args.id;
590
- var results = {};
584
+ if (_.isString(args.id)) {
585
+ if (args.skip_hooks !== true) {
586
+ yield _this4.run_hook(args, "get", "before");
587
+ } // ⚡ Include columns in cache key if specified
588
+
589
+
590
+ var key = "get::" + _this4.type + "::" + args.id + (args.columns ? "::" + args.columns : "");
591
+ var results = {};
591
592
 
592
- if (_this4.shouldUseCache(_this4.type)) {
593
- // Retrieve the cached results
594
- var cached_results = yield _this4.getCacheProviderObject(_this4.type).get(key); // Check if the cache is empty
593
+ if (_this4.shouldUseCache(_this4.type)) {
594
+ // Retrieve the cached results
595
+ var cached_results = yield _this4.getCacheProviderObject(_this4.type).get(key); // Check if the cache is empty
595
596
 
596
- var isCacheEmpty = (cached_results == null ? void 0 : cached_results.value) === undefined; // Check if the cached result should be refreshed
597
+ var isCacheEmpty = (cached_results == null ? void 0 : cached_results.value) === undefined; // Check if the cached result should be refreshed
597
598
 
598
- var shouldRefresh = yield _this4.shouldForceRefresh(cached_results); // Force a refresh for "workflow" type if needed
599
+ var shouldRefresh = yield _this4.shouldForceRefresh(cached_results); // Force a refresh for "workflow" type if needed
599
600
 
600
- if (isCacheEmpty || shouldRefresh) {
601
- // Retrieve from the database and update cache
602
- var pDb = p,
603
- cDb = pDb == null ? void 0 : pDb.start(_this4.type + ".get.database");
601
+ if (isCacheEmpty || shouldRefresh) {
602
+ // Retrieve from the database and update cache
603
+ if (p) {
604
+ results = yield p.track(_this4.type + ".get.database",
605
+ /*#__PURE__*/
606
+ _asyncToGenerator(function* () {
607
+ return yield _this4.database.get(args.id);
608
+ }));
609
+ } else {
610
+ results = yield _this4.database.get(args.id);
611
+ }
604
612
 
605
- try {
613
+ yield _this4.getCacheProviderObject(_this4.type).set(key, {
614
+ value: results,
615
+ time: new Date().getTime()
616
+ }, _this4.getCacheConfig(_this4.type));
617
+ } else {
618
+ // Use the cached value
619
+ results = cached_results.value;
620
+ }
621
+ } else {
622
+ // Directly fetch from the database if caching is disabled
623
+ if (p) {
624
+ results = yield p.track(_this4.type + ".get.database",
625
+ /*#__PURE__*/
626
+ _asyncToGenerator(function* () {
627
+ return yield _this4.database.get(args.id);
628
+ }));
629
+ } else {
606
630
  results = yield _this4.database.get(args.id);
607
- } finally {
608
- cDb && pDb.end(cDb);
609
631
  }
632
+ }
610
633
 
611
- yield _this4.getCacheProviderObject(_this4.type).set(key, {
612
- value: results,
613
- time: new Date().getTime()
614
- }, _this4.getCacheConfig(_this4.type));
615
- } else {
616
- // Use the cached value
617
- results = cached_results.value;
634
+ if (results.type !== undefined && results.type !== _this4.type) {
635
+ throw new Error(_this4.type + " does not exist type");
618
636
  }
619
- } else {
620
- // Directly fetch from the database if caching is disabled
621
- var _pDb = p,
622
- _cDb = _pDb == null ? void 0 : _pDb.start(_this4.type + ".get.database");
623
637
 
624
- try {
625
- results = yield _this4.database.get(args.id);
626
- } finally {
627
- _cDb && _pDb.end(_cDb);
638
+ if (results._type !== undefined && results._type !== _this4.type) {
639
+ throw new Error(_this4.type + " does not exist _type");
628
640
  }
629
- }
630
641
 
631
- if (results.type !== undefined && results.type !== _this4.type) {
632
- throw new Error(_this4.type + " does not exist type");
633
- }
642
+ if (results.deleted === undefined || results.deleted === false) {
643
+ if (args.skip_read_serialize !== true && args.skip_serialize !== true) {
644
+ // ⚡ Pass columns to do_serialize so it can skip irrelevant modifiers
645
+ results = yield _this4.do_serialize(results, "read", {}, args, (yield _this4.propsToBeRemoved(results)));
646
+ } // ⚡ OPTIMIZED: Filter results by columns if specified
634
647
 
635
- if (results._type !== undefined && results._type !== _this4.type) {
636
- throw new Error(_this4.type + " does not exist _type");
637
- }
638
648
 
639
- if (results.deleted === undefined || results.deleted === false) {
640
- if (args.skip_read_serialize !== true && args.skip_serialize !== true) {
641
- results = yield _this4.do_serialize(results, "read", {}, args, (yield _this4.propsToBeRemoved(results)));
642
- }
649
+ if (args.columns) {
650
+ results = _this4.filterResultsByColumns([results], args.columns)[0];
651
+ }
643
652
 
644
- if (args.skip_hooks !== true) {
645
- yield _this4.run_hook(results, "get", "after");
646
- }
653
+ if (args.skip_hooks !== true) {
654
+ yield _this4.run_hook(results, "get", "after");
655
+ }
647
656
 
648
- return results;
649
- } else {
650
- throw new Error(_this4.type + " does not exist");
657
+ return results;
658
+ } else {
659
+ throw new Error(_this4.type + " does not exist");
660
+ }
651
661
  }
662
+ });
663
+
664
+ return function doGet() {
665
+ return _ref2.apply(this, arguments);
666
+ };
667
+ }();
668
+
669
+ try {
670
+ if (p) {
671
+ var _args6;
672
+
673
+ return yield p.track(_this4.type + ".get", doGet, {
674
+ id: (_args6 = args) == null ? void 0 : _args6.id
675
+ });
652
676
  }
677
+
678
+ return yield doGet();
653
679
  } catch (e) {
654
680
  console.log(e.message, e);
655
681
  throw e;
656
- } finally {
657
- c && p.end(c);
658
682
  }
659
683
  })();
660
684
  }
@@ -762,71 +786,86 @@ class SpiceModel {
762
786
  return _asyncToGenerator(function* () {
763
787
  var _this8$_ctx;
764
788
 
765
- // Profiling: zero overhead when disabled (single falsy check)
766
- var p = (_this8$_ctx = _this8[_ctx]) == null ? void 0 : _this8$_ctx.profiler,
767
- c = p == null ? void 0 : p.start(_this8.type + ".update", {
768
- id: args == null ? void 0 : args.id
769
- });
789
+ // Profiling: use track() for proper async context forking
790
+ var p = (_this8$_ctx = _this8[_ctx]) == null ? void 0 : _this8$_ctx.profiler;
770
791
 
771
- try {
772
- _this8.updated_at = new SDate().now();
773
- var results = yield _this8.database.get(args.id);
774
- var item_exist = yield _this8.exist(results);
792
+ var doUpdate =
793
+ /*#__PURE__*/
794
+ function () {
795
+ var _ref5 = _asyncToGenerator(function* () {
796
+ _this8.updated_at = new SDate().now();
797
+ var results = yield _this8.database.get(args.id);
798
+ var item_exist = yield _this8.exist(results);
775
799
 
776
- if (!item_exist) {
777
- throw new Error(_this8.type + " does not exist. in update");
778
- }
800
+ if (!item_exist) {
801
+ throw new Error(_this8.type + " does not exist. in update");
802
+ }
779
803
 
780
- delete results["id"];
804
+ delete results["id"];
781
805
 
782
- _.defaults(_this8, results);
806
+ _.defaults(_this8, results);
783
807
 
784
- var cover_obj = {
785
- old: results,
786
- new: _this8,
787
- id: args.id
788
- };
789
- var form;
808
+ var cover_obj = {
809
+ old: results,
810
+ new: _this8,
811
+ id: args.id
812
+ };
813
+ var form;
790
814
 
791
- if (args.skip_write_serialize != true && args.skip_serialize != true) {
792
- cover_obj.new = yield _this8.do_serialize(_this8, "write", cover_obj.new, args);
793
- }
815
+ if (args.skip_write_serialize != true && args.skip_serialize != true) {
816
+ cover_obj.new = yield _this8.do_serialize(_this8, "write", cover_obj.new, args);
817
+ }
794
818
 
795
- if (args.skip_hooks != true) {
796
- yield _this8.run_hook(cover_obj, "update", "before", results);
797
- }
819
+ if (args.skip_hooks != true) {
820
+ yield _this8.run_hook(cover_obj, "update", "before", results);
821
+ }
798
822
 
799
- var db_data = cover_obj.new || _this8;
800
- var pDb = p,
801
- cDb = pDb == null ? void 0 : pDb.start(_this8.type + ".update.database");
823
+ var db_data = cover_obj.new || _this8;
802
824
 
803
- try {
804
- yield _this8.database.update(args.id, db_data, args._ttl);
805
- } finally {
806
- cDb && pDb.end(cDb);
807
- }
825
+ if (p) {
826
+ yield p.track(_this8.type + ".update.database",
827
+ /*#__PURE__*/
828
+ _asyncToGenerator(function* () {
829
+ yield _this8.database.update(args.id, db_data, args._ttl);
830
+ }));
831
+ } else {
832
+ yield _this8.database.update(args.id, db_data, args._ttl);
833
+ }
808
834
 
809
- _this8.setMonitor();
835
+ _this8.setMonitor();
810
836
 
811
- if (args.skip_read_serialize != true && args.skip_serialize != true) {
812
- cover_obj.new = yield _this8.do_serialize(cover_obj.new, "read", {}, args, (yield _this8.propsToBeRemoved(cover_obj.new)));
813
- }
837
+ if (args.skip_read_serialize != true && args.skip_serialize != true) {
838
+ cover_obj.new = yield _this8.do_serialize(cover_obj.new, "read", {}, args, (yield _this8.propsToBeRemoved(cover_obj.new)));
839
+ }
814
840
 
815
- if (args.skip_hooks != true) {
816
- yield _this8.run_hook(_extends({}, _this8, {
841
+ if (args.skip_hooks != true) {
842
+ yield _this8.run_hook(_extends({}, _this8, {
843
+ id: args.id
844
+ }), "update", "after", results);
845
+ }
846
+
847
+ _this8.id = args.id;
848
+ return _extends({}, cover_obj.new, {
817
849
  id: args.id
818
- }), "update", "after", results);
850
+ });
851
+ });
852
+
853
+ return function doUpdate() {
854
+ return _ref5.apply(this, arguments);
855
+ };
856
+ }();
857
+
858
+ try {
859
+ if (p) {
860
+ return yield p.track(_this8.type + ".update", doUpdate, {
861
+ id: args == null ? void 0 : args.id
862
+ });
819
863
  }
820
864
 
821
- _this8.id = args.id;
822
- return _extends({}, cover_obj.new, {
823
- id: args.id
824
- });
865
+ return yield doUpdate();
825
866
  } catch (e) {
826
867
  console.log("Error on update", e, e.stack);
827
868
  throw e;
828
- } finally {
829
- c && p.end(c);
830
869
  }
831
870
  })();
832
871
  }
@@ -841,70 +880,85 @@ class SpiceModel {
841
880
  args = {};
842
881
  }
843
882
 
844
- // Profiling: zero overhead when disabled (single falsy check)
845
- var p = (_this9$_ctx = _this9[_ctx]) == null ? void 0 : _this9$_ctx.profiler,
846
- c = p == null ? void 0 : p.start(_this9.type + ".create");
883
+ // Profiling: use track() for proper async context forking
884
+ var p = (_this9$_ctx = _this9[_ctx]) == null ? void 0 : _this9$_ctx.profiler;
885
+
886
+ var doCreate =
887
+ /*#__PURE__*/
888
+ function () {
889
+ var _ref7 = _asyncToGenerator(function* () {
890
+ var form;
891
+ _this9.created_at = new SDate().now();
892
+ args = _.defaults(args, {
893
+ id_prefix: _this9.type
894
+ });
847
895
 
848
- try {
849
- var form;
850
- _this9.created_at = new SDate().now();
851
- args = _.defaults(args, {
852
- id_prefix: _this9.type
853
- });
896
+ if (args.body) {
897
+ form = _.defaults({}, args.body);
898
+ form.created_at = _this9.created_at;
899
+ form.updated_at = _this9.created_at;
900
+ delete form["bucket"];
901
+ }
854
902
 
855
- if (args.body) {
856
- form = _.defaults({}, args.body);
857
- form.created_at = _this9.created_at;
858
- form.updated_at = _this9.created_at;
859
- delete form["bucket"];
860
- }
903
+ var workingForm = form || _this9;
904
+ _this9.updated_at = new SDate().now();
905
+ var id = args.id_prefix + "-" + UUID.v4();
861
906
 
862
- var workingForm = form || _this9;
863
- _this9.updated_at = new SDate().now();
864
- var id = args.id_prefix + "-" + UUID.v4();
907
+ if (args && args.id) {
908
+ id = args.id;
909
+ }
865
910
 
866
- if (args && args.id) {
867
- id = args.id;
868
- }
911
+ if (args.skip_write_serialize != true && args.skip_serialize != true) {
912
+ workingForm = yield _this9.do_serialize(workingForm, "write", {}, args);
913
+ }
869
914
 
870
- if (args.skip_write_serialize != true && args.skip_serialize != true) {
871
- workingForm = yield _this9.do_serialize(workingForm, "write", {}, args);
872
- }
915
+ if (args.skip_hooks != true) {
916
+ yield _this9.run_hook(workingForm, "create", "before");
917
+ }
873
918
 
874
- if (args.skip_hooks != true) {
875
- yield _this9.run_hook(workingForm, "create", "before");
876
- }
919
+ var results;
877
920
 
878
- var pDb = p,
879
- cDb = pDb == null ? void 0 : pDb.start(_this9.type + ".create.database");
880
- var results;
921
+ if (p) {
922
+ results = yield p.track(_this9.type + ".create.database",
923
+ /*#__PURE__*/
924
+ _asyncToGenerator(function* () {
925
+ return yield _this9.database.insert(id, workingForm, args._ttl);
926
+ }));
927
+ } else {
928
+ results = yield _this9.database.insert(id, workingForm, args._ttl);
929
+ }
881
930
 
882
- try {
883
- results = yield _this9.database.insert(id, workingForm, args._ttl);
884
- } finally {
885
- cDb && pDb.end(cDb);
886
- }
931
+ _this9.setMonitor();
887
932
 
888
- _this9.setMonitor();
933
+ if (args.skip_read_serialize != true && args.skip_serialize != true) {
934
+ results = yield _this9.do_serialize(results, "read", {}, args, (yield _this9.propsToBeRemoved(results)));
935
+ }
889
936
 
890
- if (args.skip_read_serialize != true && args.skip_serialize != true) {
891
- results = yield _this9.do_serialize(results, "read", {}, args, (yield _this9.propsToBeRemoved(results)));
892
- }
937
+ if (args.skip_hooks != true) {
938
+ yield _this9.run_hook(_extends({}, results, {
939
+ id
940
+ }), "create", "after");
941
+ }
893
942
 
894
- if (args.skip_hooks != true) {
895
- yield _this9.run_hook(_extends({}, results, {
943
+ return _extends({}, results, {
896
944
  id
897
- }), "create", "after");
945
+ });
946
+ });
947
+
948
+ return function doCreate() {
949
+ return _ref7.apply(this, arguments);
950
+ };
951
+ }();
952
+
953
+ try {
954
+ if (p) {
955
+ return yield p.track(_this9.type + ".create", doCreate);
898
956
  }
899
957
 
900
- return _extends({}, results, {
901
- id
902
- });
958
+ return yield doCreate();
903
959
  } catch (e) {
904
960
  console.log(e.stack);
905
961
  throw e;
906
- } finally {
907
- c && p.end(c);
908
962
  }
909
963
  })();
910
964
  }
@@ -936,53 +990,76 @@ class SpiceModel {
936
990
  return _asyncToGenerator(function* () {
937
991
  var _this11$_ctx;
938
992
 
939
- // Profiling: zero overhead when disabled (single falsy check)
940
- var p = (_this11$_ctx = _this11[_ctx]) == null ? void 0 : _this11$_ctx.profiler,
941
- c = p == null ? void 0 : p.start(_this11.type + ".delete", {
942
- id: args == null ? void 0 : args.id
943
- });
993
+ // Profiling: use track() for proper async context forking
994
+ var p = (_this11$_ctx = _this11[_ctx]) == null ? void 0 : _this11$_ctx.profiler;
944
995
 
945
- try {
946
- var item_exist = yield _this11.exist(args.id);
996
+ var doDelete =
997
+ /*#__PURE__*/
998
+ function () {
999
+ var _ref9 = _asyncToGenerator(function* () {
1000
+ var item_exist = yield _this11.exist(args.id);
947
1001
 
948
- if (!item_exist) {
949
- throw new Error(_this11.type + " does not exist.");
950
- }
1002
+ if (!item_exist) {
1003
+ throw new Error(_this11.type + " does not exist.");
1004
+ }
951
1005
 
952
- var results = yield _this11.database.get(args.id);
1006
+ var results = yield _this11.database.get(args.id);
953
1007
 
954
- if (args.skip_hooks != true) {
955
- yield _this11.run_hook(args, "delete", "before");
956
- }
1008
+ if (args.skip_hooks != true) {
1009
+ yield _this11.run_hook(args, "delete", "before");
1010
+ }
1011
+
1012
+ var delete_response = {};
957
1013
 
958
- var delete_response = {};
959
- var pDb = p,
960
- cDb = pDb == null ? void 0 : pDb.start(_this11.type + ".delete.database");
1014
+ var dbOperation =
1015
+ /*#__PURE__*/
1016
+ function () {
1017
+ var _ref10 = _asyncToGenerator(function* () {
1018
+ if (args.hard) {
1019
+ delete_response = yield _this11.database.delete(args.id);
1020
+
1021
+ _this11.setMonitor();
1022
+ } else {
1023
+ delete results["id"];
1024
+ results.deleted = true;
1025
+ delete_response = yield _this11.database.update(args.id, results);
1026
+ }
1027
+ });
961
1028
 
962
- try {
963
- if (args.hard) {
964
- delete_response = yield _this11.database.delete(args.id);
1029
+ return function dbOperation() {
1030
+ return _ref10.apply(this, arguments);
1031
+ };
1032
+ }();
965
1033
 
966
- _this11.setMonitor();
1034
+ if (p) {
1035
+ yield p.track(_this11.type + ".delete.database", dbOperation);
967
1036
  } else {
968
- delete results["id"];
969
- results.deleted = true;
970
- delete_response = yield _this11.database.update(args.id, results);
1037
+ yield dbOperation();
971
1038
  }
972
- } finally {
973
- cDb && pDb.end(cDb);
974
- }
975
1039
 
976
- if (args.skip_hooks != true) {
977
- yield _this11.run_hook(results, "delete", "after", results);
1040
+ if (args.skip_hooks != true) {
1041
+ yield _this11.run_hook(results, "delete", "after", results);
1042
+ }
1043
+
1044
+ return {};
1045
+ });
1046
+
1047
+ return function doDelete() {
1048
+ return _ref9.apply(this, arguments);
1049
+ };
1050
+ }();
1051
+
1052
+ try {
1053
+ if (p) {
1054
+ return yield p.track(_this11.type + ".delete", doDelete, {
1055
+ id: args == null ? void 0 : args.id
1056
+ });
978
1057
  }
979
1058
 
980
- return {};
1059
+ return yield doDelete();
981
1060
  } catch (e) {
982
1061
  console.log(e.stack);
983
1062
  throw e;
984
- } finally {
985
- c && p.end(c);
986
1063
  }
987
1064
  })();
988
1065
  }
@@ -1137,12 +1214,12 @@ class SpiceModel {
1137
1214
 
1138
1215
  createJoinSection(mappedNestings) {
1139
1216
  if (!mappedNestings || mappedNestings.length === 0) return "";
1140
- return mappedNestings.map((_ref2) => {
1217
+ return mappedNestings.map((_ref11) => {
1141
1218
  var {
1142
1219
  alias,
1143
1220
  reference,
1144
1221
  is_array
1145
- } = _ref2;
1222
+ } = _ref11;
1146
1223
  var keyspace = (0, _fix.fixCollection)(reference);
1147
1224
 
1148
1225
  if (is_array === true) {
@@ -1226,117 +1303,132 @@ class SpiceModel {
1226
1303
  var _this12 = this;
1227
1304
 
1228
1305
  return _asyncToGenerator(function* () {
1229
- var _this12$_ctx, _args7, _args8;
1306
+ var _this12$_ctx;
1230
1307
 
1231
1308
  if (args === void 0) {
1232
1309
  args = {};
1233
1310
  }
1234
1311
 
1235
- // Profiling: zero overhead when disabled (single falsy check)
1236
- var p = (_this12$_ctx = _this12[_ctx]) == null ? void 0 : _this12$_ctx.profiler,
1237
- c = p == null ? void 0 : p.start(_this12.type + ".list", {
1238
- limit: (_args7 = args) == null ? void 0 : _args7.limit,
1239
- offset: (_args8 = args) == null ? void 0 : _args8.offset
1240
- });
1241
-
1242
- try {
1243
- var _args9, _args10, _args11;
1244
-
1245
- if (args.mapping_dept) _this12[_mapping_dept] = args.mapping_dept; // Find alias tokens from query/columns/sort
1312
+ // Profiling: use track() for proper async context forking
1313
+ var p = (_this12$_ctx = _this12[_ctx]) == null ? void 0 : _this12$_ctx.profiler;
1246
1314
 
1247
- var nestings = [..._this12.extractNestings(((_args9 = args) == null ? void 0 : _args9.query) || "", _this12.type), ..._this12.extractNestings(((_args10 = args) == null ? void 0 : _args10.columns) || "", _this12.type), ..._this12.extractNestings(((_args11 = args) == null ? void 0 : _args11.sort) || "", _this12.type)]; // Decide which aliases we can join: only when map.type===MODEL AND reference is a STRING keyspace.
1315
+ var doList =
1316
+ /*#__PURE__*/
1317
+ function () {
1318
+ var _ref12 = _asyncToGenerator(function* () {
1319
+ var _args7, _args8, _args9;
1248
1320
 
1249
- var mappedNestings = _.compact(_.uniq(nestings).map(alias => {
1250
- var prop = _this12.props[alias];
1251
- if (!(prop == null ? void 0 : prop.map) || prop.map.type !== _2.MapType.MODEL) return null;
1252
- var ref = prop.map.reference;
1321
+ if (args.mapping_dept) _this12[_mapping_dept] = args.mapping_dept; // Find alias tokens from query/columns/sort
1253
1322
 
1254
- if (typeof ref !== "string") {
1255
- // reference is a class/function/array-of-classes → no SQL join; serializer will handle it
1256
- return null;
1257
- }
1323
+ var nestings = [..._this12.extractNestings(((_args7 = args) == null ? void 0 : _args7.query) || "", _this12.type), ..._this12.extractNestings(((_args8 = args) == null ? void 0 : _args8.columns) || "", _this12.type), ..._this12.extractNestings(((_args9 = args) == null ? void 0 : _args9.sort) || "", _this12.type)]; // Decide which aliases we can join: only when map.type===MODEL AND reference is a STRING keyspace.
1258
1324
 
1259
- var is_array = prop.type === "array" || prop.type === Array || prop.type === _2.DataType.ARRAY;
1260
- return {
1261
- alias,
1262
- reference: ref.toLowerCase(),
1263
- // keyspace to join
1264
- is_array,
1265
- type: prop.type,
1266
- value_field: prop.map.value_field,
1267
- destination: prop.map.destination || alias
1268
- };
1269
- }));
1325
+ var mappedNestings = _.compact(_.uniq(nestings).map(alias => {
1326
+ var prop = _this12.props[alias];
1327
+ if (!(prop == null ? void 0 : prop.map) || prop.map.type !== _2.MapType.MODEL) return null;
1328
+ var ref = prop.map.reference;
1270
1329
 
1271
- var protectedAliases = mappedNestings.map(m => m.alias);
1272
- var arrayAliases = mappedNestings.filter(m => m.is_array).map(m => m.alias); // Columns: first prepare (prefix base table, rewrite array alias.field ARRAY proj),
1273
- // then normalize names and add default aliases
1330
+ if (typeof ref !== "string") {
1331
+ // reference is a class/function/array-of-classes no SQL join; serializer will handle it
1332
+ return null;
1333
+ }
1274
1334
 
1275
- args.columns = _this12.prepColumns(args.columns, protectedAliases, arrayAliases);
1276
- args.columns = _this12.fixColumnName(args.columns, protectedAliases); // Build JOIN/NEST from the mapped keyspaces
1335
+ var is_array = prop.type === "array" || prop.type === Array || prop.type === _2.DataType.ARRAY;
1336
+ return {
1337
+ alias,
1338
+ reference: ref.toLowerCase(),
1339
+ // keyspace to join
1340
+ is_array,
1341
+ type: prop.type,
1342
+ value_field: prop.map.value_field,
1343
+ destination: prop.map.destination || alias
1344
+ };
1345
+ }));
1346
+
1347
+ var protectedAliases = mappedNestings.map(m => m.alias);
1348
+ var arrayAliases = mappedNestings.filter(m => m.is_array).map(m => m.alias); // Columns: first prepare (prefix base table, rewrite array alias.field → ARRAY proj),
1349
+ // then normalize names and add default aliases
1350
+
1351
+ args.columns = _this12.prepColumns(args.columns, protectedAliases, arrayAliases);
1352
+ args.columns = _this12.fixColumnName(args.columns, protectedAliases); // Build JOIN/NEST from the mapped keyspaces
1353
+
1354
+ args._join = _this12.createJoinSection(mappedNestings); // WHERE
1355
+
1356
+ var query = "";
1357
+ var deletedCondition = "(`" + _this12.type + "`.deleted = false OR `" + _this12.type + "`.deleted IS MISSING)";
1358
+
1359
+ if (args.is_full_text === "true" || args.is_custom_query === "true") {
1360
+ query = args.query || "";
1361
+ } else if (args.filters) {
1362
+ query = _this12.makeQueryFromFilter(args.filters);
1363
+ } else if (args.query) {
1364
+ query = args.query + " AND " + deletedCondition;
1365
+ } else {
1366
+ query = deletedCondition;
1367
+ }
1277
1368
 
1278
- args._join = _this12.createJoinSection(mappedNestings); // WHERE
1369
+ if ((0, _Security.hasSQLInjection)(query)) return []; // LIMIT/OFFSET/SORT
1279
1370
 
1280
- var query = "";
1281
- var deletedCondition = "(`" + _this12.type + "`.deleted = false OR `" + _this12.type + "`.deleted IS MISSING)";
1371
+ args.limit = Number(args.limit) || undefined;
1372
+ args.offset = Number(args.offset) || 0;
1373
+ args.sort = args.sort ? args.sort.split(",").map(item => item.includes(".") ? item : "`" + _this12.type + "`." + _this12.formatSortComponent(item)).join(",") : "`" + _this12.type + "`.created_at DESC";
1282
1374
 
1283
- if (args.is_full_text === "true" || args.is_custom_query === "true") {
1284
- query = args.query || "";
1285
- } else if (args.filters) {
1286
- query = _this12.makeQueryFromFilter(args.filters);
1287
- } else if (args.query) {
1288
- query = args.query + " AND " + deletedCondition;
1289
- } else {
1290
- query = deletedCondition;
1291
- }
1375
+ if (args.skip_hooks !== true) {
1376
+ yield _this12.run_hook(_this12, "list", "before");
1377
+ }
1292
1378
 
1293
- if ((0, _Security.hasSQLInjection)(query)) return []; // LIMIT/OFFSET/SORT
1379
+ var cacheKey = "list::" + _this12.type + "::" + args._join + "::" + query + "::" + args.limit + "::" + args.offset + "::" + args.sort + "::" + args.do_count + "::" + args.statement_consistent + "::" + args.columns + "::" + args.is_full_text + "::" + args.is_custom_query;
1380
+ var results;
1294
1381
 
1295
- args.limit = Number(args.limit) || undefined;
1296
- args.offset = Number(args.offset) || 0;
1297
- args.sort = args.sort ? args.sort.split(",").map(item => item.includes(".") ? item : "`" + _this12.type + "`." + _this12.formatSortComponent(item)).join(",") : "`" + _this12.type + "`.created_at DESC";
1382
+ if (_this12.shouldUseCache(_this12.type)) {
1383
+ var cached = yield _this12.getCacheProviderObject(_this12.type).get(cacheKey);
1384
+ results = cached == null ? void 0 : cached.value;
1385
+ var isEmpty = (cached == null ? void 0 : cached.value) === undefined;
1386
+ var refresh = yield _this12.shouldForceRefresh(cached);
1298
1387
 
1299
- if (args.skip_hooks !== true) {
1300
- yield _this12.run_hook(_this12, "list", "before");
1301
- }
1388
+ if (isEmpty || refresh) {
1389
+ results = yield _this12.fetchResults(args, query);
1302
1390
 
1303
- var cacheKey = "list::" + _this12.type + "::" + args._join + "::" + query + "::" + args.limit + "::" + args.offset + "::" + args.sort + "::" + args.do_count + "::" + args.statement_consistent + "::" + args.columns + "::" + args.is_full_text + "::" + args.is_custom_query;
1304
- var results;
1391
+ _this12.getCacheProviderObject(_this12.type).set(cacheKey, {
1392
+ value: results,
1393
+ time: new Date().getTime()
1394
+ }, _this12.getCacheConfig(_this12.type));
1395
+ }
1396
+ } else {
1397
+ results = yield _this12.fetchResults(args, query);
1398
+ } // Serializer still handles class-based refs and value_field
1305
1399
 
1306
- if (_this12.shouldUseCache(_this12.type)) {
1307
- var cached = yield _this12.getCacheProviderObject(_this12.type).get(cacheKey);
1308
- results = cached == null ? void 0 : cached.value;
1309
- var isEmpty = (cached == null ? void 0 : cached.value) === undefined;
1310
- var refresh = yield _this12.shouldForceRefresh(cached);
1311
1400
 
1312
- if (isEmpty || refresh) {
1313
- results = yield _this12.fetchResults(args, query);
1401
+ if (args.skip_read_serialize !== true && args.skip_serialize !== true) {
1402
+ results.data = yield _this12.do_serialize(results.data, "read", {}, args, (yield _this12.propsToBeRemoved(results.data)));
1403
+ }
1314
1404
 
1315
- _this12.getCacheProviderObject(_this12.type).set(cacheKey, {
1316
- value: results,
1317
- time: new Date().getTime()
1318
- }, _this12.getCacheConfig(_this12.type));
1405
+ if (args.skip_hooks !== true) {
1406
+ yield _this12.run_hook(results.data, "list", "after");
1319
1407
  }
1320
- } else {
1321
- results = yield _this12.fetchResults(args, query);
1322
- } // Serializer still handles class-based refs and value_field
1323
1408
 
1409
+ results.data = _this12.filterResultsByColumns(results.data, args.columns);
1410
+ return results;
1411
+ });
1324
1412
 
1325
- if (args.skip_read_serialize !== true && args.skip_serialize !== true) {
1326
- results.data = yield _this12.do_serialize(results.data, "read", {}, args, (yield _this12.propsToBeRemoved(results.data)));
1327
- }
1413
+ return function doList() {
1414
+ return _ref12.apply(this, arguments);
1415
+ };
1416
+ }();
1417
+
1418
+ try {
1419
+ if (p) {
1420
+ var _args10, _args11;
1328
1421
 
1329
- if (args.skip_hooks !== true) {
1330
- yield _this12.run_hook(results.data, "list", "after");
1422
+ return yield p.track(_this12.type + ".list", doList, {
1423
+ limit: (_args10 = args) == null ? void 0 : _args10.limit,
1424
+ offset: (_args11 = args) == null ? void 0 : _args11.offset
1425
+ });
1331
1426
  }
1332
1427
 
1333
- results.data = _this12.filterResultsByColumns(results.data, args.columns);
1334
- return results;
1428
+ return yield doList();
1335
1429
  } catch (e) {
1336
1430
  console.log(e.stack);
1337
1431
  throw e;
1338
- } finally {
1339
- c && p.end(c);
1340
1432
  }
1341
1433
  })();
1342
1434
  }
@@ -1347,31 +1439,42 @@ class SpiceModel {
1347
1439
  return _asyncToGenerator(function* () {
1348
1440
  var _this13$_ctx;
1349
1441
 
1350
- // Profiling: zero overhead when disabled (single falsy check)
1351
- var p = (_this13$_ctx = _this13[_ctx]) == null ? void 0 : _this13$_ctx.profiler,
1352
- c = p == null ? void 0 : p.start(_this13.type + ".fetchResults");
1442
+ // Profiling: use track() for proper async context forking
1443
+ var p = (_this13$_ctx = _this13[_ctx]) == null ? void 0 : _this13$_ctx.profiler;
1444
+
1445
+ var doFetch =
1446
+ /*#__PURE__*/
1447
+ function () {
1448
+ var _ref13 = _asyncToGenerator(function* () {
1449
+ if (args.is_custom_query === "true" && args.ids.length > 0) {
1450
+ return yield _this13.database.query(query);
1451
+ } else if (args.is_full_text === "true") {
1452
+ return yield _this13.database.full_text_search(_this13.type, query || "", args.limit, args.offset, args._join);
1453
+ } else {
1454
+ var result = yield _this13.database.search(_this13.type, args.columns || "", query || "", args.limit, args.offset, args.sort, args.do_count, args.statement_consistent, args._join);
1455
+ return result;
1456
+ }
1457
+ });
1353
1458
 
1354
- try {
1355
- if (args.is_custom_query === "true" && args.ids.length > 0) {
1356
- return yield _this13.database.query(query);
1357
- } else if (args.is_full_text === "true") {
1358
- return yield _this13.database.full_text_search(_this13.type, query || "", args.limit, args.offset, args._join);
1359
- } else {
1360
- var result = yield _this13.database.search(_this13.type, args.columns || "", query || "", args.limit, args.offset, args.sort, args.do_count, args.statement_consistent, args._join);
1361
- return result;
1362
- }
1363
- } finally {
1364
- c && p.end(c);
1459
+ return function doFetch() {
1460
+ return _ref13.apply(this, arguments);
1461
+ };
1462
+ }();
1463
+
1464
+ if (p) {
1465
+ return yield p.track(_this13.type + ".fetchResults", doFetch);
1365
1466
  }
1467
+
1468
+ return yield doFetch();
1366
1469
  })();
1367
1470
  }
1368
1471
 
1369
- addHook(_ref3) {
1472
+ addHook(_ref14) {
1370
1473
  var {
1371
1474
  operation,
1372
1475
  when,
1373
1476
  execute
1374
- } = _ref3;
1477
+ } = _ref14;
1375
1478
 
1376
1479
  this[_hooks][operation][when].push(execute);
1377
1480
  }
@@ -1596,14 +1699,19 @@ class SpiceModel {
1596
1699
  })();
1597
1700
  }
1598
1701
 
1599
- addModifier(_ref4) {
1702
+ addModifier(_ref15) {
1600
1703
  var {
1601
1704
  when,
1602
- execute
1603
- } = _ref4;
1705
+ execute,
1706
+ field = null
1707
+ } = _ref15;
1604
1708
 
1605
1709
  if (this[_serializers][when]) {
1606
- this[_serializers][when]["modifiers"].push(execute);
1710
+ // Store as object with field info for column-based filtering
1711
+ this[_serializers][when]["modifiers"].push({
1712
+ execute,
1713
+ field
1714
+ });
1607
1715
  }
1608
1716
  }
1609
1717
 
@@ -1632,15 +1740,19 @@ class SpiceModel {
1632
1740
  switch (properties[i].map.type) {
1633
1741
  case _2.MapType.MODEL:
1634
1742
  {
1743
+ var destinationField = properties[i].map.destination || i;
1744
+
1635
1745
  switch (properties[i].type) {
1636
1746
  case String:
1637
1747
  case "string":
1638
1748
  {
1639
1749
  _this17.addModifier({
1640
1750
  when: properties[i].map.when || "read",
1751
+ field: destinationField,
1752
+ // ⚡ Track which field this modifier populates
1641
1753
  execute: function () {
1642
1754
  var _execute = _asyncToGenerator(function* (data) {
1643
- 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]);
1755
+ return yield _this17.mapToObject(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i, destinationField, properties[i]);
1644
1756
  });
1645
1757
 
1646
1758
  function execute(_x) {
@@ -1659,9 +1771,11 @@ class SpiceModel {
1659
1771
  {
1660
1772
  _this17.addModifier({
1661
1773
  when: properties[i].map.when || "read",
1774
+ field: destinationField,
1775
+ // ⚡ Track which field this modifier populates
1662
1776
  execute: function () {
1663
1777
  var _execute2 = _asyncToGenerator(function* (data) {
1664
- 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]);
1778
+ return yield _this17.mapToObjectArray(data, _.isString(properties[i].map.reference) ? spice.models[properties[i].map.reference] : properties[i].map.reference, i, destinationField, properties[i]);
1665
1779
  });
1666
1780
 
1667
1781
  function execute(_x2) {
@@ -1690,6 +1804,35 @@ class SpiceModel {
1690
1804
  for (var i in properties) {
1691
1805
  _loop(i);
1692
1806
  }
1807
+ } // ⚡ Parse columns string into a Set for fast lookup
1808
+
1809
+
1810
+ parseRequestedColumns(columns) {
1811
+ if (!columns || columns === "") return null; // Extract field names from column specifications
1812
+ // Handles: "field", "`field`", "table.field", "`table`.`field`", "expr AS alias"
1813
+
1814
+ var fields = new Set();
1815
+ var columnList = columns.split(",").map(c => c.trim());
1816
+
1817
+ for (var col of columnList) {
1818
+ // Check for AS alias
1819
+ var aliasMatch = col.match(/\s+AS\s+`?([\w]+)`?$/i);
1820
+
1821
+ if (aliasMatch) {
1822
+ fields.add(aliasMatch[1]);
1823
+ continue;
1824
+ } // Get the last part after dots (the field name)
1825
+
1826
+
1827
+ var parts = col.replace(/`/g, "").split(".");
1828
+ var fieldName = parts[parts.length - 1];
1829
+
1830
+ if (fieldName && fieldName !== "*") {
1831
+ fields.add(fieldName);
1832
+ }
1833
+ }
1834
+
1835
+ return fields.size > 0 ? fields : null;
1693
1836
  }
1694
1837
 
1695
1838
  do_serialize(data, type, old_data, args, path_to_be_removed) {
@@ -1702,91 +1845,114 @@ class SpiceModel {
1702
1845
  path_to_be_removed = [];
1703
1846
  }
1704
1847
 
1705
- // Profiling: zero overhead when disabled (single falsy check)
1706
- var p = (_this18$_ctx = _this18[_ctx]) == null ? void 0 : _this18$_ctx.profiler,
1707
- c = p == null ? void 0 : p.start(_this18.type + ".do_serialize", {
1708
- type
1709
- });
1848
+ // Profiling: use track() for proper async context forking
1849
+ var p = (_this18$_ctx = _this18[_ctx]) == null ? void 0 : _this18$_ctx.profiler;
1710
1850
 
1711
- try {
1712
- var _this18$_serializers, _this18$_serializers$;
1851
+ var doSerialize =
1852
+ /*#__PURE__*/
1853
+ function () {
1854
+ var _ref16 = _asyncToGenerator(function* () {
1855
+ var _this18$_serializers, _this18$_serializers$;
1713
1856
 
1714
- // Early exit if serialization should not run.
1715
- if (!_this18.shouldSerializerRun(args, type)) {
1716
- return data;
1717
- } // Add external modifiers only once.
1857
+ // Early exit if serialization should not run.
1858
+ if (!_this18.shouldSerializerRun(args, type)) {
1859
+ return data;
1860
+ } // Add external modifiers only once.
1718
1861
 
1719
1862
 
1720
- if (_this18.type && !_this18[_external_modifier_loaded]) {
1721
- _this18.addExternalModifiers(_this18.type);
1863
+ if (_this18.type && !_this18[_external_modifier_loaded]) {
1864
+ _this18.addExternalModifiers(_this18.type);
1722
1865
 
1723
- _this18[_external_modifier_loaded] = true;
1724
- } // Cache the modifiers lookup for the specified type.
1866
+ _this18[_external_modifier_loaded] = true;
1867
+ } // OPTIMIZED: Parse requested columns for selective modifier execution
1725
1868
 
1726
1869
 
1727
- var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || [];
1870
+ var requestedColumns = _this18.parseRequestedColumns(args == null ? void 0 : args.columns); // Cache the modifiers lookup for the specified type.
1728
1871
 
1729
- for (var modifier of modifiers) {
1730
- try {
1731
- data = yield modifier(data, old_data, _this18[_ctx], _this18.type);
1732
- } catch (error) {
1733
- console.error("Modifier error in do_serialize:", error.stack);
1734
- }
1735
- } // Ensure data is always an array for consistent processing.
1872
+
1873
+ var modifiers = ((_this18$_serializers = _this18[_serializers]) == null ? void 0 : (_this18$_serializers$ = _this18$_serializers[type]) == null ? void 0 : _this18$_serializers$.modifiers) || [];
1874
+
1875
+ for (var modifier of modifiers) {
1876
+ try {
1877
+ // ⚡ OPTIMIZED: Skip field-specific modifiers if columns specified and field not requested
1878
+ if (requestedColumns && modifier.field && !requestedColumns.has(modifier.field)) {
1879
+ continue; // Skip this modifier - field not in requested columns
1880
+ } // Execute modifier (supports both old function format and new object format)
1736
1881
 
1737
1882
 
1738
- var originalIsArray = Array.isArray(data);
1883
+ var executeFn = typeof modifier === "function" ? modifier : modifier.execute;
1884
+ data = yield executeFn(data, old_data, _this18[_ctx], _this18.type);
1885
+ } catch (error) {
1886
+ console.error("Modifier error in do_serialize:", error.stack);
1887
+ }
1888
+ } // Ensure data is always an array for consistent processing.
1739
1889
 
1740
- if (!originalIsArray) {
1741
- data = [data];
1742
- } // ⚡ OPTIMIZED: Use cached defaults metadata instead of computing every time
1743
1890
 
1891
+ var originalIsArray = Array.isArray(data);
1744
1892
 
1745
- var {
1746
- staticDefaults,
1747
- dynamicDefaults,
1748
- hasDefaults
1749
- } = _this18.getDefaultsMetadata(type);
1893
+ if (!originalIsArray) {
1894
+ data = [data];
1895
+ } // ⚡ OPTIMIZED: Use cached defaults metadata instead of computing every time
1750
1896
 
1751
- if (hasDefaults) {
1752
- data = data.map(item => {
1753
- // Apply static defaults first (fast - no function calls)
1754
- var result = _.defaults({}, item, staticDefaults); // Only compute dynamic defaults if there are any
1755
1897
 
1898
+ var {
1899
+ staticDefaults,
1900
+ dynamicDefaults,
1901
+ hasDefaults
1902
+ } = _this18.getDefaultsMetadata(type);
1756
1903
 
1757
- for (var {
1758
- key,
1759
- fn
1760
- } of dynamicDefaults) {
1761
- if (result[key] === undefined) {
1762
- result[key] = fn({
1763
- old_data: data,
1764
- new_data: old_data
1765
- });
1904
+ if (hasDefaults) {
1905
+ data = data.map(item => {
1906
+ // Apply static defaults first (fast - no function calls)
1907
+ var result = _.defaults({}, item, staticDefaults); // Only compute dynamic defaults if there are any
1908
+
1909
+
1910
+ for (var {
1911
+ key,
1912
+ fn
1913
+ } of dynamicDefaults) {
1914
+ if (result[key] === undefined) {
1915
+ result[key] = fn({
1916
+ old_data: data,
1917
+ new_data: old_data
1918
+ });
1919
+ }
1766
1920
  }
1767
- }
1768
1921
 
1769
- return result;
1770
- });
1771
- } // If type is "read", clean the data by omitting certain props.
1922
+ return result;
1923
+ });
1924
+ } // If type is "read", clean the data by omitting certain props.
1925
+
1926
+
1927
+ if (type === "read") {
1928
+ // ⚡ OPTIMIZED: Use cached hidden props instead of computing every time
1929
+ var hiddenProps = _this18.getHiddenProps(); // Combine default props to remove.
1772
1930
 
1773
1931
 
1774
- if (type === "read") {
1775
- // OPTIMIZED: Use cached hidden props instead of computing every time
1776
- var hiddenProps = _this18.getHiddenProps(); // Combine default props to remove.
1932
+ var propsToClean = ["deleted", "type", ...path_to_be_removed, ...hiddenProps];
1933
+ data = data.map(item => _.omit(item, propsToClean));
1934
+ } // Return in the original format (array or single object).
1777
1935
 
1778
1936
 
1779
- var propsToClean = ["deleted", "type", ...path_to_be_removed, ...hiddenProps];
1780
- data = data.map(item => _.omit(item, propsToClean));
1781
- } // Return in the original format (array or single object).
1937
+ return originalIsArray ? data : data[0];
1938
+ });
1939
+
1940
+ return function doSerialize() {
1941
+ return _ref16.apply(this, arguments);
1942
+ };
1943
+ }();
1782
1944
 
1945
+ try {
1946
+ if (p) {
1947
+ return yield p.track(_this18.type + ".do_serialize", doSerialize, {
1948
+ type
1949
+ });
1950
+ }
1783
1951
 
1784
- return originalIsArray ? data : data[0];
1952
+ return yield doSerialize();
1785
1953
  } catch (error) {
1786
1954
  console.error("Error in do_serialize:", error.stack);
1787
1955
  throw error;
1788
- } finally {
1789
- c && p.end(c);
1790
1956
  }
1791
1957
  })();
1792
1958
  }