@graphql-inspector/core 3.2.0 → 3.3.0

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.
Files changed (3) hide show
  1. package/index.js +70 -68
  2. package/index.mjs +70 -68
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -696,6 +696,70 @@ function changesInUnion(oldUnion, newUnion, addChange) {
696
696
  });
697
697
  }
698
698
 
699
+ function compareTwoStrings(str1, str2) {
700
+ if (!str1.length && !str2.length)
701
+ return 1;
702
+ if (!str1.length || !str2.length)
703
+ return 0;
704
+ if (str1.toUpperCase() === str2.toUpperCase())
705
+ return 1;
706
+ if (str1.length === 1 && str2.length === 1)
707
+ return 0;
708
+ const pairs1 = wordLetterPairs(str1);
709
+ const pairs2 = wordLetterPairs(str2);
710
+ const union = pairs1.length + pairs2.length;
711
+ let intersection = 0;
712
+ pairs1.forEach((pair1) => {
713
+ for (let i = 0, pair2; (pair2 = pairs2[i]); i++) {
714
+ if (pair1 !== pair2)
715
+ continue;
716
+ intersection++;
717
+ pairs2.splice(i, 1);
718
+ break;
719
+ }
720
+ });
721
+ return (intersection * 2) / union;
722
+ }
723
+ function findBestMatch(mainString, targetStrings) {
724
+ if (!areArgsValid(mainString, targetStrings))
725
+ throw new Error('Bad arguments: First argument should be a string, second should be an array of strings');
726
+ const ratings = targetStrings.map((target) => ({
727
+ target,
728
+ rating: compareTwoStrings(mainString, target.value),
729
+ }));
730
+ const bestMatch = Array.from(ratings).sort((a, b) => b.rating - a.rating)[0];
731
+ return { ratings, bestMatch };
732
+ }
733
+ function flattenDeep(arr) {
734
+ return Array.isArray(arr)
735
+ ? arr.reduce((a, b) => a.concat(flattenDeep(b)), [])
736
+ : [arr];
737
+ }
738
+ function areArgsValid(mainString, targetStrings) {
739
+ if (typeof mainString !== 'string')
740
+ return false;
741
+ if (!Array.isArray(targetStrings))
742
+ return false;
743
+ if (!targetStrings.length)
744
+ return false;
745
+ if (targetStrings.find((s) => typeof s.value !== 'string'))
746
+ return false;
747
+ return true;
748
+ }
749
+ function letterPairs(str) {
750
+ const pairs = [];
751
+ for (let i = 0, max = str.length - 1; i < max; i++)
752
+ pairs[i] = str.substring(i, i + 2);
753
+ return pairs;
754
+ }
755
+ function wordLetterPairs(str) {
756
+ const pairs = str.toUpperCase().split(' ').map(letterPairs);
757
+ return flattenDeep(pairs);
758
+ }
759
+ function safeString(obj) {
760
+ return inspect(obj).replace(/\[Object\: null prototype\] /g, '').replace(/(^')|('$)/g, '');
761
+ }
762
+
699
763
  function inputFieldRemoved(input, field) {
700
764
  return {
701
765
  criticality: {
@@ -756,10 +820,10 @@ function inputFieldDefaultValueChanged(input, oldField, newField) {
756
820
  return {
757
821
  criticality: {
758
822
  level: exports.CriticalityLevel.Dangerous,
759
- reason: 'Changing the default value for an argument may change the runtime behaviour of a field if it was never provided.',
823
+ reason: 'Changing the default value for an argument may change the runtime behavior of a field if it was never provided.',
760
824
  },
761
825
  type: exports.ChangeType.InputFieldDefaultValueChanged,
762
- message: `Input field '${input.name}.${oldField.name}' default value changed from '${oldField.defaultValue}' to '${newField.defaultValue}'`,
826
+ message: `Input field '${input.name}.${oldField.name}' default value changed from '${safeString(oldField.defaultValue)}' to '${safeString(newField.defaultValue)}'`,
763
827
  path: [input.name, oldField.name].join('.'),
764
828
  };
765
829
  }
@@ -965,8 +1029,10 @@ function fieldTypeChanged(type, oldField, newField) {
965
1029
  };
966
1030
  }
967
1031
  function fieldArgumentAdded(type, field, arg) {
1032
+ const isBreaking = graphql.isNonNullType(arg.type) && typeof arg.defaultValue === 'undefined';
1033
+ const defaultValueMsg = typeof arg.defaultValue !== 'undefined' ? ' (with default value) ' : ' ';
968
1034
  return {
969
- criticality: graphql.isNonNullType(arg.type)
1035
+ criticality: isBreaking
970
1036
  ? {
971
1037
  level: exports.CriticalityLevel.Breaking,
972
1038
  reason: `Adding a required argument to an existing field is a breaking change because it will cause existing uses of this field to error.`,
@@ -976,7 +1042,7 @@ function fieldArgumentAdded(type, field, arg) {
976
1042
  reason: `Adding a new argument to an existing field may involve a change in resolve function logic that potentially may cause some side effects.`,
977
1043
  },
978
1044
  type: exports.ChangeType.FieldArgumentAdded,
979
- message: `Argument '${arg.name}: ${arg.type}' added to field '${type.name}.${field.name}'`,
1045
+ message: `Argument '${arg.name}: ${arg.type}'${defaultValueMsg}added to field '${type.name}.${field.name}'`,
980
1046
  path: [type.name, field.name, arg.name].join('.'),
981
1047
  };
982
1048
  }
@@ -992,70 +1058,6 @@ function fieldArgumentRemoved(type, field, arg) {
992
1058
  };
993
1059
  }
994
1060
 
995
- function compareTwoStrings(str1, str2) {
996
- if (!str1.length && !str2.length)
997
- return 1;
998
- if (!str1.length || !str2.length)
999
- return 0;
1000
- if (str1.toUpperCase() === str2.toUpperCase())
1001
- return 1;
1002
- if (str1.length === 1 && str2.length === 1)
1003
- return 0;
1004
- const pairs1 = wordLetterPairs(str1);
1005
- const pairs2 = wordLetterPairs(str2);
1006
- const union = pairs1.length + pairs2.length;
1007
- let intersection = 0;
1008
- pairs1.forEach((pair1) => {
1009
- for (let i = 0, pair2; (pair2 = pairs2[i]); i++) {
1010
- if (pair1 !== pair2)
1011
- continue;
1012
- intersection++;
1013
- pairs2.splice(i, 1);
1014
- break;
1015
- }
1016
- });
1017
- return (intersection * 2) / union;
1018
- }
1019
- function findBestMatch(mainString, targetStrings) {
1020
- if (!areArgsValid(mainString, targetStrings))
1021
- throw new Error('Bad arguments: First argument should be a string, second should be an array of strings');
1022
- const ratings = targetStrings.map((target) => ({
1023
- target,
1024
- rating: compareTwoStrings(mainString, target.value),
1025
- }));
1026
- const bestMatch = Array.from(ratings).sort((a, b) => b.rating - a.rating)[0];
1027
- return { ratings, bestMatch };
1028
- }
1029
- function flattenDeep(arr) {
1030
- return Array.isArray(arr)
1031
- ? arr.reduce((a, b) => a.concat(flattenDeep(b)), [])
1032
- : [arr];
1033
- }
1034
- function areArgsValid(mainString, targetStrings) {
1035
- if (typeof mainString !== 'string')
1036
- return false;
1037
- if (!Array.isArray(targetStrings))
1038
- return false;
1039
- if (!targetStrings.length)
1040
- return false;
1041
- if (targetStrings.find((s) => typeof s.value !== 'string'))
1042
- return false;
1043
- return true;
1044
- }
1045
- function letterPairs(str) {
1046
- const pairs = [];
1047
- for (let i = 0, max = str.length - 1; i < max; i++)
1048
- pairs[i] = str.substring(i, i + 2);
1049
- return pairs;
1050
- }
1051
- function wordLetterPairs(str) {
1052
- const pairs = str.toUpperCase().split(' ').map(letterPairs);
1053
- return flattenDeep(pairs);
1054
- }
1055
- function safeString(obj) {
1056
- return inspect(obj).replace(/\[Object\: null prototype\] /g, '');
1057
- }
1058
-
1059
1061
  function fieldArgumentDescriptionChanged(type, field, oldArg, newArg) {
1060
1062
  return {
1061
1063
  criticality: {
package/index.mjs CHANGED
@@ -692,6 +692,70 @@ function changesInUnion(oldUnion, newUnion, addChange) {
692
692
  });
693
693
  }
694
694
 
695
+ function compareTwoStrings(str1, str2) {
696
+ if (!str1.length && !str2.length)
697
+ return 1;
698
+ if (!str1.length || !str2.length)
699
+ return 0;
700
+ if (str1.toUpperCase() === str2.toUpperCase())
701
+ return 1;
702
+ if (str1.length === 1 && str2.length === 1)
703
+ return 0;
704
+ const pairs1 = wordLetterPairs(str1);
705
+ const pairs2 = wordLetterPairs(str2);
706
+ const union = pairs1.length + pairs2.length;
707
+ let intersection = 0;
708
+ pairs1.forEach((pair1) => {
709
+ for (let i = 0, pair2; (pair2 = pairs2[i]); i++) {
710
+ if (pair1 !== pair2)
711
+ continue;
712
+ intersection++;
713
+ pairs2.splice(i, 1);
714
+ break;
715
+ }
716
+ });
717
+ return (intersection * 2) / union;
718
+ }
719
+ function findBestMatch(mainString, targetStrings) {
720
+ if (!areArgsValid(mainString, targetStrings))
721
+ throw new Error('Bad arguments: First argument should be a string, second should be an array of strings');
722
+ const ratings = targetStrings.map((target) => ({
723
+ target,
724
+ rating: compareTwoStrings(mainString, target.value),
725
+ }));
726
+ const bestMatch = Array.from(ratings).sort((a, b) => b.rating - a.rating)[0];
727
+ return { ratings, bestMatch };
728
+ }
729
+ function flattenDeep(arr) {
730
+ return Array.isArray(arr)
731
+ ? arr.reduce((a, b) => a.concat(flattenDeep(b)), [])
732
+ : [arr];
733
+ }
734
+ function areArgsValid(mainString, targetStrings) {
735
+ if (typeof mainString !== 'string')
736
+ return false;
737
+ if (!Array.isArray(targetStrings))
738
+ return false;
739
+ if (!targetStrings.length)
740
+ return false;
741
+ if (targetStrings.find((s) => typeof s.value !== 'string'))
742
+ return false;
743
+ return true;
744
+ }
745
+ function letterPairs(str) {
746
+ const pairs = [];
747
+ for (let i = 0, max = str.length - 1; i < max; i++)
748
+ pairs[i] = str.substring(i, i + 2);
749
+ return pairs;
750
+ }
751
+ function wordLetterPairs(str) {
752
+ const pairs = str.toUpperCase().split(' ').map(letterPairs);
753
+ return flattenDeep(pairs);
754
+ }
755
+ function safeString(obj) {
756
+ return inspect(obj).replace(/\[Object\: null prototype\] /g, '').replace(/(^')|('$)/g, '');
757
+ }
758
+
695
759
  function inputFieldRemoved(input, field) {
696
760
  return {
697
761
  criticality: {
@@ -752,10 +816,10 @@ function inputFieldDefaultValueChanged(input, oldField, newField) {
752
816
  return {
753
817
  criticality: {
754
818
  level: CriticalityLevel.Dangerous,
755
- reason: 'Changing the default value for an argument may change the runtime behaviour of a field if it was never provided.',
819
+ reason: 'Changing the default value for an argument may change the runtime behavior of a field if it was never provided.',
756
820
  },
757
821
  type: ChangeType.InputFieldDefaultValueChanged,
758
- message: `Input field '${input.name}.${oldField.name}' default value changed from '${oldField.defaultValue}' to '${newField.defaultValue}'`,
822
+ message: `Input field '${input.name}.${oldField.name}' default value changed from '${safeString(oldField.defaultValue)}' to '${safeString(newField.defaultValue)}'`,
759
823
  path: [input.name, oldField.name].join('.'),
760
824
  };
761
825
  }
@@ -961,8 +1025,10 @@ function fieldTypeChanged(type, oldField, newField) {
961
1025
  };
962
1026
  }
963
1027
  function fieldArgumentAdded(type, field, arg) {
1028
+ const isBreaking = isNonNullType(arg.type) && typeof arg.defaultValue === 'undefined';
1029
+ const defaultValueMsg = typeof arg.defaultValue !== 'undefined' ? ' (with default value) ' : ' ';
964
1030
  return {
965
- criticality: isNonNullType(arg.type)
1031
+ criticality: isBreaking
966
1032
  ? {
967
1033
  level: CriticalityLevel.Breaking,
968
1034
  reason: `Adding a required argument to an existing field is a breaking change because it will cause existing uses of this field to error.`,
@@ -972,7 +1038,7 @@ function fieldArgumentAdded(type, field, arg) {
972
1038
  reason: `Adding a new argument to an existing field may involve a change in resolve function logic that potentially may cause some side effects.`,
973
1039
  },
974
1040
  type: ChangeType.FieldArgumentAdded,
975
- message: `Argument '${arg.name}: ${arg.type}' added to field '${type.name}.${field.name}'`,
1041
+ message: `Argument '${arg.name}: ${arg.type}'${defaultValueMsg}added to field '${type.name}.${field.name}'`,
976
1042
  path: [type.name, field.name, arg.name].join('.'),
977
1043
  };
978
1044
  }
@@ -988,70 +1054,6 @@ function fieldArgumentRemoved(type, field, arg) {
988
1054
  };
989
1055
  }
990
1056
 
991
- function compareTwoStrings(str1, str2) {
992
- if (!str1.length && !str2.length)
993
- return 1;
994
- if (!str1.length || !str2.length)
995
- return 0;
996
- if (str1.toUpperCase() === str2.toUpperCase())
997
- return 1;
998
- if (str1.length === 1 && str2.length === 1)
999
- return 0;
1000
- const pairs1 = wordLetterPairs(str1);
1001
- const pairs2 = wordLetterPairs(str2);
1002
- const union = pairs1.length + pairs2.length;
1003
- let intersection = 0;
1004
- pairs1.forEach((pair1) => {
1005
- for (let i = 0, pair2; (pair2 = pairs2[i]); i++) {
1006
- if (pair1 !== pair2)
1007
- continue;
1008
- intersection++;
1009
- pairs2.splice(i, 1);
1010
- break;
1011
- }
1012
- });
1013
- return (intersection * 2) / union;
1014
- }
1015
- function findBestMatch(mainString, targetStrings) {
1016
- if (!areArgsValid(mainString, targetStrings))
1017
- throw new Error('Bad arguments: First argument should be a string, second should be an array of strings');
1018
- const ratings = targetStrings.map((target) => ({
1019
- target,
1020
- rating: compareTwoStrings(mainString, target.value),
1021
- }));
1022
- const bestMatch = Array.from(ratings).sort((a, b) => b.rating - a.rating)[0];
1023
- return { ratings, bestMatch };
1024
- }
1025
- function flattenDeep(arr) {
1026
- return Array.isArray(arr)
1027
- ? arr.reduce((a, b) => a.concat(flattenDeep(b)), [])
1028
- : [arr];
1029
- }
1030
- function areArgsValid(mainString, targetStrings) {
1031
- if (typeof mainString !== 'string')
1032
- return false;
1033
- if (!Array.isArray(targetStrings))
1034
- return false;
1035
- if (!targetStrings.length)
1036
- return false;
1037
- if (targetStrings.find((s) => typeof s.value !== 'string'))
1038
- return false;
1039
- return true;
1040
- }
1041
- function letterPairs(str) {
1042
- const pairs = [];
1043
- for (let i = 0, max = str.length - 1; i < max; i++)
1044
- pairs[i] = str.substring(i, i + 2);
1045
- return pairs;
1046
- }
1047
- function wordLetterPairs(str) {
1048
- const pairs = str.toUpperCase().split(' ').map(letterPairs);
1049
- return flattenDeep(pairs);
1050
- }
1051
- function safeString(obj) {
1052
- return inspect(obj).replace(/\[Object\: null prototype\] /g, '');
1053
- }
1054
-
1055
1057
  function fieldArgumentDescriptionChanged(type, field, oldArg, newArg) {
1056
1058
  return {
1057
1059
  criticality: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-inspector/core",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Tooling for GraphQL. Compare GraphQL Schemas, check documents, find breaking changes, find similar types.",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {