spice-js 2.6.38 → 2.6.40

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.
@@ -784,333 +784,190 @@ export default class SpiceModel {
784
784
  JSON.stringify(this);
785
785
  }
786
786
 
787
- async list(args) {
788
- try {
789
- if (!args) {
790
- args = {};
791
- }
787
+ prepColumns(columns) {
788
+ if (columns && columns !== "") {
789
+ let columnList = columns.split(",");
790
+ return _.join(
791
+ _.compact(
792
+ columnList.map((column) => {
793
+ if (column === "meta().id") return undefined;
794
+ if (!column.startsWith("`") && !column.endsWith("`")) {
795
+ column = `\`${column}\``;
796
+ }
797
+ if (
798
+ column &&
799
+ !column.includes(".") &&
800
+ !column.startsWith(this.type)
801
+ ) {
802
+ column = `\`${this.type}\`.${column}`;
803
+ }
804
+ return column;
805
+ })
806
+ ),
807
+ ","
808
+ );
809
+ }
810
+ return columns;
811
+ }
792
812
 
793
- function prepColumns(columns) {
794
- if (columns && columns != "") {
795
- let columnList = columns.split(","); // Convert comma-separated string to array
796
- return _.join(
797
- _.compact(
798
- _.map(columnList, (column) => {
799
- if (column == "meta().id") {
800
- column = undefined;
801
- } else if (!column.startsWith("`") && !column.endsWith("`")) {
802
- `\`${column}\``;
803
- }
804
- if (column) {
805
- if (!column.includes(".") && !column.startsWith(that.type)) {
806
- column = `\`${that.type}\`.${column}`;
807
- }
808
- }
809
- return column;
810
- })
811
- ),
812
- ","
813
- );
814
- }
815
- return columns;
816
- }
813
+ filterResultsByColumns(data, columns) {
814
+ if (columns && columns !== "") {
815
+ columns = columns.replace(/`/g, "").replace(/meta\(\)\.id/g, "id");
816
+ let columnList = columns
817
+ .split(",")
818
+ .map((column) =>
819
+ column.includes(".") ? _.last(column.split(".")) : column
820
+ );
821
+ columnList.push("_permissions", "_permissions_", "id");
822
+ return data.map((entry) => _.pick(entry, columnList));
823
+ }
824
+ return data;
825
+ }
817
826
 
818
- let query = "";
819
- args.columns = prepColumns(args.columns);
820
- function filterResultsByColumns(data, columns) {
821
- if (columns && columns != "") {
822
- columns = columns.replace(/`/g, "");
823
- columns = columns.replace(/meta\(\)\.id/g, "id");
824
- let columnList = columns.split(",").map((column) => {
825
- //if colums has a . then remove the first part of the string
826
- return column.includes(".") ? _.last(column.split(".")) : column;
827
- }); // Convert comma-separated string to array
828
- columnList.push("_permissions"); // Always include _permissions
829
- columnList.push("_permissions_"); // Always include _permissions
830
- columnList.push("id"); // Always include _permissions
831
- return _.map(data, (entry) => _.pick(entry, columnList));
832
- }
833
- return data;
827
+ extractNestings(string, localType) {
828
+ let returnVal = [];
829
+ let regex = /(`?\w+`?)\.(`?\w+`?)/g;
830
+ let match;
831
+
832
+ while ((match = regex.exec(string)) !== null) {
833
+ let first = match[1].replace(/`/g, "");
834
+ if (first !== localType) {
835
+ returnVal.push(first);
834
836
  }
837
+ }
835
838
 
836
- function extractNestings(string, localType) {
837
- let returnVal = [];
839
+ let queryRegex = /(ANY|EVERY)\s+\w+\s+IN\s+`?(\w+)`?/g;
840
+ let queryMatch;
838
841
 
839
- // Regex for nested properties, including backtick-quoted ones
840
- let regex = /(`?\w+`?)\.(`?\w+`?)/g;
841
- let match;
842
+ while ((queryMatch = queryRegex.exec(string)) !== null) {
843
+ returnVal.push(queryMatch[2]);
844
+ }
842
845
 
843
- while ((match = regex.exec(string)) !== null) {
844
- let first = match[1].replace(/`/g, "");
845
- let second = match[2].replace(/`/g, "");
846
- if (first !== localType) {
847
- returnVal.push(first);
848
- }
849
- }
850
- // Regex for ANY/EVERY clauses
851
- let queryRegex = /(ANY|EVERY)\s+\w+\s+IN\s+`?(\w+)`?/g;
852
- let queryMatch;
846
+ return [...new Set(returnVal)];
847
+ }
853
848
 
854
- while ((queryMatch = queryRegex.exec(string)) !== null) {
855
- returnVal.push(queryMatch[2]);
849
+ createJoinSection(nestings) {
850
+ return nestings
851
+ .map((nesting) => {
852
+ if (
853
+ nesting.type === DataType.ARRAY ||
854
+ nesting.type === Array ||
855
+ nesting.type === "array"
856
+ ) {
857
+ return `LEFT NEST \`${fixCollection(nesting.reference)}\` AS \`${nesting.alias}\` ON KEYS \`${this.type}\`.\`${nesting.alias}\``;
858
+ } else {
859
+ return `LEFT JOIN \`${fixCollection(nesting.reference)}\` AS \`${nesting.alias}\` ON KEYS \`${this.type}\`.\`${nesting.alias}\``;
856
860
  }
861
+ })
862
+ .join(" ");
863
+ }
857
864
 
858
- return [...new Set(returnVal)]; // Remove duplicates
859
- }
860
-
861
- /* function extractNestings(string, localType) {
862
- let returnVal = [];
863
- let regex = /(\w+)\.(\w+)/g;
864
- let match;
865
-
866
- while ((match = regex.exec(string)) !== null) {
867
- if (match[1] !== localType) {
868
- returnVal.push(match[1]);
869
- } else {
870
- returnVal.push(match[2]);
871
- }
872
- }
865
+ formatSortComponent(sortComponent) {
866
+ const parts = sortComponent.split(" ");
867
+ parts[0] = `\`${parts[0]}\``;
868
+ return parts.join(" ");
869
+ }
873
870
 
874
- return [...new Set(returnVal)]; // Remove duplicates
875
- } */
876
- /* function extractNestings(string, localType) {
877
- let returnVal = [];
878
- let regex = /(\w+)\./g;
879
- let match = regex.exec(string);
880
- console.log("Local:", localType, match);
881
- while (match) {
882
- if (match[1] != localType) returnVal.push(match[1]);
883
- }
884
- return returnVal;
885
- } */
871
+ removeSpaceAndSpecialCharacters(str) {
872
+ return str.replace(/[^a-zA-Z0-9]/g, "");
873
+ }
886
874
 
887
- //console.log("Query", args?.query);
875
+ async list(args = {}) {
876
+ try {
877
+ args.columns = this.prepColumns(args.columns);
888
878
 
889
- let nestings = [
890
- ...extractNestings(args?.query, this.type),
891
- ...extractNestings(args?.columns, this.type),
892
- ...extractNestings(args?.sort, this.type),
879
+ const nestings = [
880
+ ...this.extractNestings(args?.query, this.type),
881
+ ...this.extractNestings(args?.columns, this.type),
882
+ ...this.extractNestings(args?.sort, this.type),
893
883
  ];
894
- let mappedNestings = _.compact(
895
- _.map(_.uniq(nestings), (nesting) => {
896
- let prop = this.props[nesting];
897
- if (prop) {
898
- if (prop.map) {
899
- if (prop.map.type == MapType.MODEL) {
900
- return {
901
- alias: nesting,
902
- reference: prop.map.reference.toLowerCase(),
903
- type: prop.type,
904
- value_field: prop.map.value_field,
905
- };
906
- }
907
- }
884
+
885
+ const mappedNestings = _.compact(
886
+ _.uniq(nestings).map((nesting) => {
887
+ const prop = this.props[nesting];
888
+ if (prop?.map?.type === MapType.MODEL) {
889
+ return {
890
+ alias: nesting,
891
+ reference: prop.map.reference.toLowerCase(),
892
+ type: prop.type,
893
+ value_field: prop.map.value_field,
894
+ };
908
895
  }
909
896
  })
910
897
  );
911
898
 
912
- function createJoinSection(nestings) {
913
- //create join section with nestings
914
- let joinSection = "";
915
- _.each(nestings, (nesting) => {
916
- if (
917
- nesting.type == DataType.ARRAY ||
918
- nesting.type == Array ||
919
- nesting.type == "array"
920
- ) {
921
- joinSection += `LEFT NEST \`${fixCollection(nesting.reference)}\` AS \`${nesting.alias}\` ON KEYS \`${that.type}\`.\`${nesting.alias}\` `;
922
- } else {
923
- joinSection += `LEFT JOIN \`${fixCollection(nesting.reference)}\` AS \`${nesting.alias}\` ON KEYS \`${that.type}\`.\`${nesting.alias}\` `;
924
- }
925
- });
926
- return joinSection;
927
- }
928
- let _join = createJoinSection(mappedNestings);
929
- //console.log("Props", that.type, nestings, _join, args?.query);
930
-
931
- args._join = _join;
899
+ args._join = this.createJoinSection(mappedNestings);
932
900
 
933
- if (
934
- (args.is_full_text && args.is_full_text === "true") ||
935
- (args.is_custom_query && args.is_custom_query === "true")
936
- ) {
901
+ let query = "";
902
+ if (args.is_full_text === "true" || args.is_custom_query === "true") {
937
903
  query = args.query;
938
904
  } else {
939
- if (args.filters) {
940
- query = this.makeQueryFromFilter(args.filters);
941
- } else {
942
- if (args.query) {
943
- query =
944
- args.query +
945
- ` AND (\`${this.type}\`.deleted = false OR \`${this.type}\`.deleted IS MISSING) `;
946
- } else {
947
- query = `(\`${this.type}\`.deleted = false OR \`${this.type}\`.deleted IS MISSING) `;
948
- }
949
- }
950
- }
951
-
952
- function formatSortComponent(sortComponent) {
953
- // Split the string by spaces to get individual parts
954
- const parts = sortComponent.split(" ");
955
- // Assuming the first part is the column name, add backticks around it
956
- parts[0] = `\`${parts[0]}\``;
957
- // Rejoin the parts back into a string and return
958
- return parts.join(" ");
905
+ query = args.filters
906
+ ? this.makeQueryFromFilter(args.filters)
907
+ : args.query
908
+ ? `${args.query} AND (\`${this.type}\`.deleted = false OR \`${this.type}\`.deleted IS MISSING)`
909
+ : `(\`${this.type}\`.deleted = false OR \`${this.type}\`.deleted IS MISSING)`;
959
910
  }
960
911
 
961
912
  if (hasSQLInjection(query)) {
962
913
  return [];
963
914
  }
964
- if (args.limit) {
965
- args.limit = Number(args.limit);
966
- }
967
- if (args.offset) {
968
- args.offset = Number(args.offset);
969
- }
970
915
 
971
- if (!args.sort) {
972
- args.sort = `\`${this.type}\`.created_at DESC`;
973
- } else {
974
- let sort_array = args.sort.split(",");
975
- // check the first string in each item in the array to see if it contains a . if not then add the type
976
- let new_sort_array = [];
977
- for (let i = 0; i < sort_array.length; i++) {
978
- if (!sort_array[i].includes(".")) {
979
- new_sort_array.push(
980
- `\`${this.type}\`.${formatSortComponent(sort_array[i])}`
981
- );
982
- } else {
983
- new_sort_array.push(sort_array[i]);
984
- }
985
- }
986
- args.sort = _.join(new_sort_array, ",");
987
- }
988
- if (args.skip_hooks != true) {
916
+ args.limit = Number(args.limit) || undefined;
917
+ args.offset = Number(args.offset) || 0;
918
+ args.sort = args.sort
919
+ ? args.sort
920
+ .split(",")
921
+ .map((item) =>
922
+ item.includes(".")
923
+ ? item
924
+ : `\`${this.type}\`.${this.formatSortComponent(item)}`
925
+ )
926
+ .join(",")
927
+ : `\`${this.type}\`.created_at DESC`;
928
+
929
+ if (args.skip_hooks !== true) {
989
930
  await this.run_hook(this, "list", "before");
990
931
  }
991
- function removeSpaceAndSpecialCharacters(str) {
992
- return str.replace(/[^a-zA-Z0-9]/g, "");
993
- }
994
- let key = removeSpaceAndSpecialCharacters(
932
+
933
+ const cacheKey = this.removeSpaceAndSpecialCharacters(
995
934
  `list::${this.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}`
996
935
  );
997
936
 
998
937
  let results;
999
- if (args.is_custom_query && args.is_custom_query === "true") {
1000
- if (args.ids.length > 0) {
1001
- if (this.shouldUseCache(this.type)) {
1002
- let cached_results = await this.getCacheProviderObject(
1003
- this.type
1004
- ).get(key);
1005
- results = cached_results?.value;
1006
- if (
1007
- cached_results?.value == undefined ||
1008
- (await this.shouldForceRefresh(cached_results))
1009
- ) {
1010
- results = await this.database.query(query);
1011
- this.getCacheProviderObject(this.type).set(
1012
- key,
1013
- { value: results, time: new Date().getTime() },
1014
- this.getCacheConfig(this.type)
1015
- );
1016
- }
1017
- } else {
1018
- results = await this.database.query(query);
1019
- }
938
+ if (this.shouldUseCache(this.type)) {
939
+ const cachedResults = await this.getCacheProviderObject(this.type).get(
940
+ cacheKey
941
+ );
942
+ results = cachedResults?.value;
943
+
944
+ if (!results || (await this.shouldForceRefresh(cachedResults))) {
945
+ results = await this.fetchResults(args, query);
946
+ await this.getCacheProviderObject(this.type).set(
947
+ cacheKey,
948
+ { value: results, time: new Date().getTime() },
949
+ this.getCacheConfig(this.type)
950
+ );
1020
951
  }
1021
952
  } else {
1022
- if (args.is_full_text && args.is_full_text === "true") {
1023
- if (this.shouldUseCache(this.type)) {
1024
- let cached_results = await this.getCacheProviderObject(
1025
- this.type
1026
- ).get(key);
1027
- results = cached_results?.value;
1028
- if (
1029
- cached_results?.value == undefined ||
1030
- (await this.shouldForceRefresh(cached_results))
1031
- ) {
1032
- results = await this.database.full_text_search(
1033
- this.type,
1034
- query || "",
1035
- args.limit,
1036
- args.offset,
1037
- args._join
1038
- );
1039
- this.getCacheProviderObject(this.type).set(
1040
- key,
1041
- { value: results, time: new Date().getTime() },
1042
- this.getCacheConfig(this.type)
1043
- );
1044
- }
1045
- } else {
1046
- results = await this.database.full_text_search(
1047
- this.type,
1048
- query || "",
1049
- args.limit,
1050
- args.offset,
1051
- args._join
1052
- );
1053
- }
1054
- } else {
1055
- if (this.shouldUseCache(this.type)) {
1056
- let cached_results = await this.getCacheProviderObject(
1057
- this.type
1058
- ).get(key);
1059
- results = cached_results?.value;
1060
- let shouleForceRefresh =
1061
- await this.shouldForceRefresh(cached_results);
1062
- if (cached_results?.value == undefined || shouleForceRefresh) {
1063
- results = await this.database.search(
1064
- this.type,
1065
- args.columns || "",
1066
- query || "",
1067
- args.limit,
1068
- args.offset,
1069
- args.sort,
1070
- args.do_count,
1071
- args.statement_consistent,
1072
- args._join
1073
- );
1074
- this.getCacheProviderObject(this.type).set(
1075
- key,
1076
- { value: results, time: new Date().getTime() },
1077
- this.getCacheConfig(this.type)
1078
- );
1079
- }
1080
- } else {
1081
- results = await this.database.search(
1082
- this.type,
1083
- args.columns || "",
1084
- query || "",
1085
- args.limit,
1086
- args.offset,
1087
- args.sort,
1088
- args.do_count,
1089
- args.statement_consistent,
1090
- args._join
1091
- );
1092
- }
1093
- }
953
+ results = await this.fetchResults(args, query);
1094
954
  }
1095
- try {
1096
- if (args.skip_read_serialize != true && args.skip_serialize != true) {
1097
- results.data = await this.do_serialize(
1098
- results.data,
1099
- "read",
1100
- {},
1101
- args,
1102
- await this.propsToBeRemoved(results.data)
1103
- );
1104
- }
1105
- if (this.type == "resourcedetail");
1106
955
 
1107
- if (args.skip_hooks != true) {
1108
- await this.run_hook(results.data, "list", "after");
1109
- }
1110
- } catch (e) {
1111
- console.log(e);
956
+ if (args.skip_read_serialize !== true && args.skip_serialize !== true) {
957
+ results.data = await this.do_serialize(
958
+ results.data,
959
+ "read",
960
+ {},
961
+ args,
962
+ await this.propsToBeRemoved(results.data)
963
+ );
1112
964
  }
1113
- results.data = filterResultsByColumns(results.data, args.columns);
965
+
966
+ if (args.skip_hooks !== true) {
967
+ await this.run_hook(results.data, "list", "after");
968
+ }
969
+
970
+ results.data = this.filterResultsByColumns(results.data, args.columns);
1114
971
  return results;
1115
972
  } catch (e) {
1116
973
  console.log(e.stack);
@@ -1118,6 +975,33 @@ export default class SpiceModel {
1118
975
  }
1119
976
  }
1120
977
 
978
+ async fetchResults(args, query) {
979
+ if (args.is_custom_query === "true" && args.ids.length > 0) {
980
+ return await this.database.query(query);
981
+ } else if (args.is_full_text === "true") {
982
+ return await this.database.full_text_search(
983
+ this.type,
984
+ query || "",
985
+ args.limit,
986
+ args.offset,
987
+ args._join
988
+ );
989
+ } else {
990
+ let result = await this.database.search(
991
+ this.type,
992
+ args.columns || "",
993
+ query || "",
994
+ args.limit,
995
+ args.offset,
996
+ args.sort,
997
+ args.do_count,
998
+ args.statement_consistent,
999
+ args._join
1000
+ );
1001
+ return result;
1002
+ }
1003
+ }
1004
+
1121
1005
  addHook({ operation, when, execute }) {
1122
1006
  this[_hooks][operation][when].push(execute);
1123
1007
  }
@@ -1,69 +1,78 @@
1
- let fs = require('fs-extra');
2
- var path = require('path');
3
- var open = require("open");
4
- let uuid = require('uuid');
5
- import _ from 'lodash';
1
+ let fs = require("fs-extra");
2
+ let uuid = require("uuid");
3
+ import _ from "lodash";
6
4
 
7
- export default class Local{
8
-
9
-
10
- constructor(args={}){
11
- this.args = args;
5
+ export default class Local {
6
+ constructor(args = {}) {
7
+ this.args = args;
8
+ }
9
+
10
+ async save({ files, path }) {
11
+ if (
12
+ _.has(files, "path") &&
13
+ _.has(files, "size") &&
14
+ _.has(files, "_writeStream")
15
+ ) {
16
+ files = { files };
12
17
  }
13
18
 
14
- async save({files, path}){
15
- if(_.has(files, 'path') && _.has(files, 'size') && _.has(files, '_writeStream')){
16
- files = {files}
19
+ files = _.reduce(
20
+ _.map(_.values(files), (file) => {
21
+ if (!_.isArray(file)) {
22
+ return Array.of(file);
17
23
  }
24
+ return file;
25
+ }),
26
+ (accu, item) => {
27
+ return [...accu, ...item];
28
+ },
29
+ []
30
+ );
18
31
 
19
- files = _.reduce(_.map(_.values(files), (file)=>{
20
- if(!_.isArray(file)){
21
- return Array.of(file)
22
- }
23
- return file;
24
- }), (accu, item)=>{
25
- return [...accu, ...item];
26
- }, []);
27
-
28
- function makeDirectory(dir) {
29
- if (!fs.existsSync(dir)) {
30
- fs.mkdirSync(dir);
31
- }
32
- }
33
- // Create folders
34
- let pathArray = path.split('/');
35
- _.reduce(pathArray, (accu, item)=>{
36
- if(item != accu){
37
- accu = _.join([accu, item], '/');
38
- }
39
- makeDirectory(accu);
40
- return accu
41
- }, pathArray[0])
32
+ function makeDirectory(dir) {
33
+ if (!fs.existsSync(dir)) {
34
+ fs.mkdirSync(dir);
35
+ }
36
+ }
37
+ // Create folders
38
+ let pathArray = path.split("/");
39
+ _.reduce(
40
+ pathArray,
41
+ (accu, item) => {
42
+ if (item != accu) {
43
+ accu = _.join([accu, item], "/");
44
+ }
45
+ makeDirectory(accu);
46
+ return accu;
47
+ },
48
+ pathArray[0]
49
+ );
42
50
 
43
- // Create read stream
44
- const readStreams = _.map(files, (file)=>{
45
- return {file, readStream: fs.createReadStream(file.path)}
46
- });
47
- // Create Write Stream
48
- ;
49
- let paths = _.map(readStreams, (item)=>{
50
- let extension = _.last(item.file.name.split("."));
51
- let file_name = _.last(uuid.v4().split("-"));
52
- let writeStream = fs.createWriteStream(`${path}/${file_name}.${extension}`);
53
- item.readStream.pipe(writeStream);
54
- item.readStream.on("end", function (err) {
55
- fs.unlink(item.file.path, function (obj) { });
56
- });
57
- return `${path}/${file_name}.${extension}`;
58
- });
51
+ // Create read stream
52
+ const readStreams = _.map(files, (file) => {
53
+ return { file, readStream: fs.createReadStream(file.path) };
54
+ });
55
+ // Create Write Stream
56
+ let paths = _.map(readStreams, (item) => {
57
+ let extension = _.last(item.file.name.split("."));
58
+ let file_name = _.last(uuid.v4().split("-"));
59
+ let writeStream = fs.createWriteStream(
60
+ `${path}/${file_name}.${extension}`
61
+ );
62
+ item.readStream.pipe(writeStream);
63
+ item.readStream.on("end", function (err) {
64
+ fs.unlink(item.file.path, function (obj) {});
65
+ });
66
+ return `${path}/${file_name}.${extension}`;
67
+ });
59
68
 
60
- if(paths.length==1){
61
- return _.first(paths);
62
- }
63
- return paths;
69
+ if (paths.length == 1) {
70
+ return _.first(paths);
64
71
  }
72
+ return paths;
73
+ }
65
74
 
66
- async delete({path}){
67
- console.log("Sending",this.args, path)
68
- }
69
- }
75
+ async delete({ path }) {
76
+ console.log("Sending", this.args, path);
77
+ }
78
+ }