示例#1
0
 .then(response => {
   const schema = JSON.parse(response.body).data
   const sdl = printSchema(buildClientSchema(schema))
   const parsedSdl = parse(sdl)
   const mutatedSdl = visit(parsedSdl, {
     ObjectTypeDefinition: {
       enter(node: ObjectTypeDefinitionNode) {
         if (
           !['Query', 'Mutation', 'Subscription'].includes(node.name.value)
         ) {
           const nodeWithValidFields = visit(node, {
             FieldDefinition: {
               enter: (fieldNode: FieldDefinitionNode) => {
                 if (
                   (fieldNode.arguments &&
                     fieldNode.arguments.length > 0 &&
                     fieldNode.type.kind === 'NamedType') ||
                   (fieldNode.type.kind === 'NonNullType' &&
                     !isScalarType(fieldNode.type))
                 ) {
                   return {
                     ...fieldNode,
                     arguments: fieldNode.arguments
                       ? fieldNode.arguments.filter(
                           arg => arg.name.value !== 'where',
                         )
                       : [],
                   }
                 } else {
                   return fieldNode
                 }
               },
             },
           })
           return nodeWithValidFields
         }
       },
     },
     EnumTypeDefinition: {
       enter(enumNode: EnumTypeDefinitionNode) {
         if (enumNode.name.value === 'PrismaDatabase') {
           return null
         }
       },
     },
     FieldDefinition: {
       enter(fieldNode: FieldDefinitionNode) {
         if (fieldNode.name.value === 'executeRaw') {
           return null
         }
       },
     },
   })
   console.log(print(mutatedSdl))
 })
export function printWithReducedWhitespace(ast: DocumentNode): string {
  // In a GraphQL AST (which notably does not contain comments), the only place
  // where meaningful whitespace (or double quotes) can exist is in
  // StringNodes. So to print with reduced whitespace, we:
  // - temporarily sanitize strings by replacing their contents with hex
  // - use the default GraphQL printer
  // - minimize the whitespace with a simple regexp replacement
  // - convert strings back to their actual value
  // We normalize all strings to non-block strings for simplicity.

  const sanitizedAST = visit(ast, {
    StringValue(node: StringValueNode): StringValueNode {
      return {
        ...node,
        value: Buffer.from(node.value, 'utf8').toString('hex'),
        block: false,
      };
    },
  });
  const withWhitespace = print(sanitizedAST);
  const minimizedButStillHex = withWhitespace
    .replace(/\s+/g, ' ')
    .replace(/([^_a-zA-Z0-9]) /g, (_, c) => c)
    .replace(/ ([^_a-zA-Z0-9])/g, (_, c) => c);
  return minimizedButStillHex.replace(/"([a-f0-9]+)"/g, (_, hex) =>
    JSON.stringify(Buffer.from(hex, 'hex').toString('utf8')),
  );
}
export function removeAliases(ast: DocumentNode): DocumentNode {
  return visit(ast, {
    Field(node: FieldNode): FieldNode {
      return {
        ...node,
        alias: undefined,
      };
    },
  });
}
示例#4
0
  public transformRequest(originalRequest: Request): Request {
    let fromSelection: SelectionSetNode;
    const ourPathFrom = JSON.stringify(this.from);
    const ourPathTo = JSON.stringify(this.to);
    let fieldPath: Array<string> = [];
    visit(originalRequest.document, {
      [Kind.FIELD]: {
        enter: (node: FieldNode) => {
          fieldPath.push(node.name.value);
          if (ourPathFrom === JSON.stringify(fieldPath)) {
            fromSelection = node.selectionSet;
            return BREAK;
          }
        },
        leave: (node: FieldNode) => {
          fieldPath.pop();
        },
      },
    });

    fieldPath = [];
    const newDocument = visit(originalRequest.document, {
      [Kind.FIELD]: {
        enter: (node: FieldNode) => {
          fieldPath.push(node.name.value);
          if (ourPathTo === JSON.stringify(fieldPath) && fromSelection) {
            return {
              ...node,
              selectionSet: fromSelection,
            };
          }
        },
        leave: (node: FieldNode) => {
          fieldPath.pop();
        },
      },
    });
    return {
      ...originalRequest,
      document: newDocument,
    };
  }
示例#5
0
 function extractFragmentName(node: ASTNode) {
     visit(node, {
         enter(node) {
             if (node.kind !== "FragmentSpread") {
                 return;
             } else if (relatedFragments.some(fragmentName => fragmentName === node.name.value)) {
                 return;
             }
             relatedFragments = [...relatedFragments, node.name.value];
         }
     });
 }
export function sortAST(ast: DocumentNode): DocumentNode {
  return visit(ast, {
    OperationDefinition(
      node: OperationDefinitionNode,
    ): OperationDefinitionNode {
      return {
        ...node,
        variableDefinitions: sorted(
          node.variableDefinitions,
          'variable.name.value',
        ),
      };
    },
    SelectionSet(node: SelectionSetNode): SelectionSetNode {
      return {
        ...node,
        // Define an ordering for field names in a SelectionSet.  Field first,
        // then FragmentSpread, then InlineFragment.  By a lovely coincidence,
        // the order we want them to appear in is alphabetical by node.kind.
        // Use sortBy instead of sorted because 'selections' is not optional.
        selections: sortBy(node.selections, 'kind', 'name.value'),
      };
    },
    Field(node: FieldNode): FieldNode {
      return {
        ...node,
        arguments: sorted(node.arguments, 'name.value'),
      };
    },
    FragmentSpread(node: FragmentSpreadNode): FragmentSpreadNode {
      return { ...node, directives: sorted(node.directives, 'name.value') };
    },
    InlineFragment(node: InlineFragmentNode): InlineFragmentNode {
      return { ...node, directives: sorted(node.directives, 'name.value') };
    },
    FragmentDefinition(node: FragmentDefinitionNode): FragmentDefinitionNode {
      return {
        ...node,
        directives: sorted(node.directives, 'name.value'),
        variableDefinitions: sorted(
          node.variableDefinitions,
          'variable.name.value',
        ),
      };
    },
    Directive(node: DirectiveNode): DirectiveNode {
      return { ...node, arguments: sorted(node.arguments, 'name.value') };
    },
  });
}
function replaceFieldsWithFragments(
  targetSchema: GraphQLSchema,
  document: DocumentNode,
  mapping: FieldToFragmentMapping,
): DocumentNode {
  const typeInfo = new TypeInfo(targetSchema);
  return visit(
    document,
    visitWithTypeInfo(typeInfo, {
      [Kind.SELECTION_SET](
        node: SelectionSetNode,
      ): SelectionSetNode | null | undefined {
        const parentType: GraphQLType = typeInfo.getParentType();
        if (parentType) {
          const parentTypeName = parentType.name;
          let selections = node.selections;

          if (mapping[parentTypeName]) {
            node.selections.forEach(selection => {
              if (selection.kind === Kind.FIELD) {
                const name = selection.name.value;
                const fragments = mapping[parentTypeName][name];
                if (fragments && fragments.length > 0) {
                  const fragment = concatInlineFragments(
                    parentTypeName,
                    fragments,
                  );
                  selections = selections.concat(fragment);
                }
              }
            });
          }

          if (selections !== node.selections) {
            return {
              ...node,
              selections,
            };
          }
        }
      },
    }),
  );
}
export function hideLiterals(ast: DocumentNode): DocumentNode {
  return visit(ast, {
    IntValue(node: IntValueNode): IntValueNode {
      return { ...node, value: '0' };
    },
    FloatValue(node: FloatValueNode): FloatValueNode {
      return { ...node, value: '0' };
    },
    StringValue(node: StringValueNode): StringValueNode {
      return { ...node, value: '', block: false };
    },
    ListValue(node: ListValueNode): ListValueNode {
      return { ...node, values: [] };
    },
    ObjectValue(node: ObjectValueNode): ObjectValueNode {
      return { ...node, fields: [] };
    },
  });
}
function addTypenameToAbstract(
  targetSchema: GraphQLSchema,
  document: DocumentNode,
): DocumentNode {
  const typeInfo = new TypeInfo(targetSchema);
  return visit(
    document,
    visitWithTypeInfo(typeInfo, {
      [Kind.SELECTION_SET](
        node: SelectionSetNode,
      ): SelectionSetNode | null | undefined {
        const parentType: GraphQLType = typeInfo.getParentType();
        let selections = node.selections;
        if (
          parentType &&
          (parentType instanceof GraphQLInterfaceType ||
            parentType instanceof GraphQLUnionType) &&
          !selections.find(
            _ =>
              (_ as FieldNode).kind === Kind.FIELD &&
              (_ as FieldNode).name.value === '__typename',
          )
        ) {
          selections = selections.concat({
            kind: Kind.FIELD,
            name: {
              kind: Kind.NAME,
              value: '__typename',
            },
          });
        }

        if (selections !== node.selections) {
          return {
            ...node,
            selections,
          };
        }
      },
    }),
  );
}
示例#10
0
 public transformRequest(originalRequest: Request): Request {
   const newDocument = visit(originalRequest.document, {
     [Kind.NAMED_TYPE]: (node: NamedTypeNode) => {
       const name = node.name.value;
       if (name in this.reverseMap) {
         return {
           ...node,
           name: {
             kind: Kind.NAME,
             value: this.reverseMap[name],
           },
         };
       }
     },
   });
   return {
     document: newDocument,
     variables: originalRequest.variables,
   };
 }