Skip to content

Commit

Permalink
💡 Add comments to patches
Browse files Browse the repository at this point in the history
  • Loading branch information
adbouygues committed Jul 12, 2024
1 parent 7737f21 commit 0c13615
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 21 deletions.
23 changes: 11 additions & 12 deletions packages/graphql-mesh/patches/@graphql-tools+stitch+9.0.3.patch
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,26 @@ index 5e752ad..3b487f5 100644
const currentNamedType = (0, graphql_1.getNamedType)(c.type);
if (finalNamedType.toString() !== currentNamedType.toString()) {
diff --git a/node_modules/@graphql-tools/stitch/cjs/typeCandidates.js b/node_modules/@graphql-tools/stitch/cjs/typeCandidates.js
index c915942..c2a322a 100644
index c915942..ae923fe 100644
--- a/node_modules/@graphql-tools/stitch/cjs/typeCandidates.js
+++ b/node_modules/@graphql-tools/stitch/cjs/typeCandidates.js
@@ -119,6 +119,29 @@ function buildTypes({ typeCandidates, directives, stitchingInfo, rootTypeNames,
@@ -119,6 +119,33 @@ function buildTypes({ typeCandidates, directives, stitchingInfo, rootTypeNames,
(typeof mergeTypes === 'function' && mergeTypes(typeCandidates[typeName], typeName)) ||
(Array.isArray(mergeTypes) && mergeTypes.includes(typeName)) ||
(stitchingInfo != null && typeName in stitchingInfo.mergedTypes)) {
+
+ // Custom object-interface stitching
+ // Special handling for object-interface stitching
+ const candidates = typeCandidates[typeName].sort((a, b) => a.subschema.name.localeCompare(b.subschema.name));
+ // Check for candidates with different constructors (e.g., object and interface)
+ if (candidates.some(candidate => candidate.type.constructor !== candidates[0].type.constructor)) {
+ const candidatesI = candidates.filter((c) => c.type.constructor.name === "GraphQLInterfaceType");
+ const candidatesObj = candidates.filter((c) => c.type.constructor.name === "GraphQLObjectType");
+ // If all the candidates are either interfaces or objects
+ if (candidatesI.length + candidatesObj.length === candidates.length) {
+ let finalI = candidatesI[0];
+ const otherCandidates = candidatesI.slice(1, candidatesI.length).concat(candidatesObj);
+ otherCandidates.forEach((otherCandidate) => {
+ // Add fields from other candidates to the final interface
+ Object.keys(otherCandidate.type._fields).forEach(field => {
+ if (finalI.type._fields[field] === undefined) {
+ finalI.type._fields[field] = otherCandidate.type._fields[field];
Expand All @@ -37,6 +40,7 @@ index c915942..c2a322a 100644
+ });
+ typeCandidates[typeName] = [finalI];
+ }
+ // Special handling for Date scalar type if it appears among the candidates
+ if (typeName === "Date") {
+ typeCandidates[typeName] = candidates.filter((c) => c.type.constructor.name === "GraphQLScalarType");
+ }
Expand All @@ -45,14 +49,12 @@ index c915942..c2a322a 100644
typeMap[typeName] = (0, mergeCandidates_js_1.mergeCandidates)(typeName, typeCandidates[typeName], typeMergingOptions);
}
else {
@@ -128,6 +151,66 @@ function buildTypes({ typeCandidates, directives, stitchingInfo, rootTypeNames,
@@ -128,6 +155,61 @@ function buildTypes({ typeCandidates, directives, stitchingInfo, rootTypeNames,
typeMap[typeName] = candidateSelector(typeCandidates[typeName]).type;
}
}
+
+ /**
+ * Really tidious edge case when an object implements more than 1 interface
+ */
+ // Handle edge case: object implementing more than one interface
+ Object.values(typeMap).forEach((type) => {
+ if (type.constructor.name === "GraphQLObjectType") {
+ const typeInterfaces = type.getInterfaces();
Expand All @@ -72,6 +74,7 @@ index c915942..c2a322a 100644
+ }
+ })
+ })
+ // Ensure duplicate fields are consistent across implementations
+ Object.keys(duplicateFields).forEach(field => {
+ if (type.getFields()[field] !== undefined) {
+ type._fields[field] = duplicateFields[field];
Expand All @@ -87,11 +90,7 @@ index c915942..c2a322a 100644
+ }
+ }
+ });
+ /**
+ * When an object implements an interface, it needs to have every property
+ * of this interface. Because interfaces have been possibly merged earlier
+ * in this file, this statement is sometimes not true anymore.
+ */
+ // Ensure object types implement all fields from their interfaces
+ Object.values(typeMap).forEach((type) => {
+ if (type.constructor.name === "GraphQLObjectType") {
+ const typeInterfaces = type.getInterfaces();
Expand Down
6 changes: 2 additions & 4 deletions packages/graphql-mesh/patches/json-machete+0.97.1.patch
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
diff --git a/node_modules/json-machete/cjs/healJSONSchema.js b/node_modules/json-machete/cjs/healJSONSchema.js
old mode 100644
new mode 100755
index 5d7e615..7d4ed0c
index 5d7e615..88ae5fb 100644
--- a/node_modules/json-machete/cjs/healJSONSchema.js
+++ b/node_modules/json-machete/cjs/healJSONSchema.js
@@ -40,12 +40,28 @@ exports.AnySchema = {
Expand Down Expand Up @@ -39,7 +37,7 @@ index 5d7e615..7d4ed0c
subSchema.enum) {
- debugLogFn?.(`${path} has a pattern or maxLength or minLength or enum but no title. Setting it to ${pathBasedName}`);
- subSchema.title = pathBasedName;
+ // Change enum names to be able to merge them
+ // Change the default enum names to be able to merge them
+ const newEnumName = `ENUM_${maybeDefinitionBasedPath.split('/')[maybeDefinitionBasedPath.split('/').length-1]}`
+ debugLogFn?.(`${path} has a enum but no title. Setting it to ${newEnumName}`);
+ subSchema.title = newEnumName;
Expand Down
15 changes: 10 additions & 5 deletions patches/@graphql-tools+executor+1.2.1.patch
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
diff --git a/node_modules/@graphql-tools/executor/cjs/execution/execute.js b/node_modules/@graphql-tools/executor/cjs/execution/execute.js
old mode 100644
new mode 100755
index 791e3df..b6a78f0
index 791e3df..ae399d9
--- a/node_modules/@graphql-tools/executor/cjs/execution/execute.js
+++ b/node_modules/@graphql-tools/executor/cjs/execution/execute.js
@@ -629,7 +629,10 @@ function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, r
@@ -628,8 +628,13 @@ function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, r
return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result, asyncPayloadRecord);
}
function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNodes, info, result) {
+ // If runtimeTypeName is null or undefined, derive it from the discriminator directive in the returnType
if (runtimeTypeName == null) {
- throw (0, utils_1.createGraphQLError)(`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, { nodes: fieldNodes });
+ // Extract version suffix from return type name
+ const suffix = returnType.name.split('_')[1]
+ runtimeTypeName = Object.values(JSON.parse(returnType.astNode.directives
+ .find(d => d.name.value === "discriminator").arguments
+ .find(a => a.name.value === "mapping").value.value))[0] + '_' + suffix
}
// releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType`
// TODO: remove in 17.0.0 release
@@ -640,6 +643,15 @@ function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNo
@@ -640,6 +645,17 @@ function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNo
throw (0, utils_1.createGraphQLError)(`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}" with ` +
`value ${(0, utils_1.inspect)(result)}, received "${(0, utils_1.inspect)(runtimeTypeName)}".`);
}
+ // Resolve type from mapping of discriminator directive when possible
+ // Resolves the type from the mapping of the discriminator directive when possible.
+ const mappedTypes = JSON.parse(returnType.astNode.directives
+ .find(d => d.name.value === "discriminator").arguments
+ .find(a => a.name.value === "mapping").value.value)
+ Object.keys(mappedTypes).forEach((type) => {
+ Object.keys(mappedTypes).forEach((type) => {
+ // For each key in the mapping object, check if the runtimeTypeName includes the key
+ if (runtimeTypeName.includes(type)) {
+ // Replace the key with its corresponding mapped type in the runtimeTypeName
+ runtimeTypeName = runtimeTypeName.replace(type, mappedTypes[type])
+ }
+ })
Expand Down

0 comments on commit 0c13615

Please sign in to comment.