Skip to content

Commit

Permalink
chore: refactor normalization factory (#528)
Browse files Browse the repository at this point in the history
  • Loading branch information
Aenimus authored Feb 19, 2024
1 parent e0345bc commit 311b2fd
Show file tree
Hide file tree
Showing 30 changed files with 4,314 additions and 2,566 deletions.
483 changes: 182 additions & 301 deletions composition-go/index.global.js

Large diffs are not rendered by default.

41 changes: 3 additions & 38 deletions composition/src/ast/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import {
TypeNode,
UnionTypeDefinitionNode,
} from 'graphql';
import { federationUnexpectedNodeKindError } from '../errors/errors';
import { formatDescription } from './utils';
import { deepCopyTypeNode } from '../schema-building/ast';

function deepCopyFieldsAndInterfaces(
node: InterfaceTypeDefinitionNode | ObjectTypeDefinitionNode | ObjectTypeExtensionNode,
Expand All @@ -50,33 +50,6 @@ export type ConstValueNodeWithValue =
| BooleanValueNode
| EnumValueNode;

export function deepCopyTypeNode(node: TypeNode, parentName: string, fieldName: string): TypeNode {
const deepCopy: MutableTypeNode = { kind: node.kind };
let lastTypeNode = deepCopy;
for (let i = 0; i < maximumTypeNesting; i++) {
switch (node.kind) {
case Kind.NAMED_TYPE:
lastTypeNode.name = { ...node.name };
return deepCopy as TypeNode;
case Kind.LIST_TYPE:
lastTypeNode.kind = node.kind;
lastTypeNode.type = { kind: node.type.kind };
lastTypeNode = lastTypeNode.type;
node = node.type;
continue;
case Kind.NON_NULL_TYPE:
lastTypeNode.kind = node.kind;
lastTypeNode.type = { kind: node.type.kind };
lastTypeNode = lastTypeNode.type;
node = node.type;
continue;
default:
throw federationUnexpectedNodeKindError(parentName, fieldName);
}
}
throw new Error(`Field ${parentName}.${fieldName} has more than 30 layers of nesting, or there is a cyclical error.`);
}

export type MutableDirectiveDefinitionNode = {
arguments?: InputValueDefinitionNode[];
description?: StringValueNode;
Expand Down Expand Up @@ -258,12 +231,12 @@ export function objectTypeDefinitionNodeToMutable(node: ObjectTypeDefinitionNode
}

export type MutableObjectTypeExtensionNode = {
description?: StringValueNode;
directives?: ConstDirectiveNode[];
fields: FieldDefinitionNode[];
interfaces: NamedTypeNode[];
kind: Kind.OBJECT_TYPE_EXTENSION;
name: NameNode;
description?: StringValueNode;
directives?: ConstDirectiveNode[];
};

export function objectTypeExtensionNodeToMutable(node: ObjectTypeExtensionNode): MutableObjectTypeExtensionNode {
Expand Down Expand Up @@ -307,14 +280,6 @@ export function scalarTypeDefinitionNodeToMutable(node: ScalarTypeDefinitionNode
};
}

export type MutableTypeNode = {
kind: Kind.NAMED_TYPE | Kind.LIST_TYPE | Kind.NON_NULL_TYPE;
name?: NameNode;
type?: MutableTypeNode;
};

export const maximumTypeNesting = 30;

export type MutableUnionTypeDefinitionNode = {
description?: StringValueNode;
directives?: ConstDirectiveNode[];
Expand Down
12 changes: 5 additions & 7 deletions composition/src/ast/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
ArgumentNode,
ConstDirectiveNode,
DocumentNode,
EnumTypeDefinitionNode,
EnumTypeExtensionNode,
FieldDefinitionNode,
FieldNode,
InputObjectTypeDefinitionNode,
Expand All @@ -15,10 +17,13 @@ import {
ObjectTypeExtensionNode,
OperationTypeNode,
parse,
ScalarTypeDefinitionNode,
ScalarTypeExtensionNode,
SchemaDefinitionNode,
SchemaExtensionNode,
SelectionSetNode,
StringValueNode,
UnionTypeDefinitionNode,
UnionTypeExtensionNode,
} from 'graphql';
import {
Expand Down Expand Up @@ -54,13 +59,6 @@ import {
UNION_UPPER,
} from '../utils/string-constants';
import { duplicateInterfaceError, unexpectedKindFatalError } from '../errors/errors';
import {
EnumTypeDefinitionNode,
EnumTypeExtensionNode,
ScalarTypeDefinitionNode,
ScalarTypeExtensionNode,
UnionTypeDefinitionNode,
} from 'graphql/index';
import { DirectiveContainer, EXECUTABLE_DIRECTIVE_LOCATIONS, NodeContainer } from '../federation/utils';

export function isObjectLikeNodeEntity(node: ObjectLikeTypeNode): boolean {
Expand Down
49 changes: 15 additions & 34 deletions composition/src/errors/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function duplicateInterfaceError(interfaceName: string, typeName: string)
return new Error(`Interface "${interfaceName}" can only be defined on type "${typeName}" once.`);
}

export function duplicateUnionMemberError(memberName: string, typeName: string): Error {
export function duplicateUnionMemberExtensionError(memberName: string, typeName: string): Error {
return new Error(`Extension error:\n Member "${memberName}" already exists on union "${typeName}".`);
}

Expand Down Expand Up @@ -163,8 +163,10 @@ export function noBaseTypeExtensionError(typeName: string): Error {
return new Error(`Extension error:\n Could not extend the type "${typeName}" because no base definition exists.`);
}

export function noDefinedUnionMembersError(unionName: string): Error {
return new Error(`The union "${unionName}" must define at least one union member.`);
export function noDefinedUnionMembersError(unionTypeName: string, extension = false): Error {
return new Error(
`The union ` + (extension ? 'extension' : '') + ` "${unionTypeName}" must define at least one union member.`,
);
}

export function operationDefinitionError(typeName: string, operationType: OperationTypeNode, actualType: Kind): Error {
Expand Down Expand Up @@ -211,10 +213,10 @@ export function shareableFieldDefinitionsError(parent: ObjectContainer, children
);
}

export function undefinedDirectiveError(directiveName: string, hostPath: string): Error {
return new Error(
export function undefinedDirectiveErrorMessage(directiveName: string, hostPath: string): string {
return (
`The directive "${directiveName}" is declared on "${hostPath}",` +
` but the directive is not defined in the schema.`,
` but the directive is not defined in the schema.`
);
}

Expand Down Expand Up @@ -288,6 +290,10 @@ export function invalidUnionError(unionName: string): Error {
return new Error(`Union "${unionName}" must have at least one member.`);
}

export function duplicateUnionMemberError(memberTypeName: string, unionTypeName: string): Error {
return new Error(`Member "${memberTypeName}" must only be defined on union "${unionTypeName}" once.`);
}

export const invalidDeprecatedDirectiveError = new Error(`
Expected the @deprecated directive to have a single optional argument "reason" of the type "String!"
`);
Expand Down Expand Up @@ -373,29 +379,6 @@ export function invalidKeyDirectiveArgumentErrorMessage(directiveKind: Kind): st
return ` The required argument named "fields" must be type "String" and not type "${directiveKind}".`;
}

export function invalidGraphQLNameErrorMessage(type: string, name: string): string {
return (
` The ${type} "${name}" is an invalid GraphQL name:\n` +
` GraphQL names must match the following regex: /[_a-zA-Z][_a-zA-Z0-9]*/`
);
}

export const invalidOpeningBraceErrorMessage: string = ` Unexpected brace opening:\n Received an opening brace "{" before the parent value was defined.`;

export const invalidClosingBraceErrorMessage: string = ` Unexpected brace closure:\n Received a closing brace "}" before any nested values were defined.`;

export const invalidNestingClosureErrorMessage: string = ` Unexpected brace closure:\n Received a closing brace "}" before its corresponding opening brace "{" was defined.`;

export const invalidNestingErrorMessage: string = ` Invalid nesting:\n A nested key was terminated without a closing brace "}".`;

export function invalidEntityKeyError(parentTypeName: string, entityKey: string, errorMessage: string): Error {
return new Error(
`The directive "key" declared on the object "${parentTypeName}"` +
` with the "fields" argument value of "${entityKey}" is invalid for the following reason:\n` +
errorMessage,
);
}

export function invalidKeyDirectivesError(parentTypeName: string, errorMessages: string[]): Error {
return new Error(
`The entity "${parentTypeName}" defines the following invalid "key" directive` +
Expand Down Expand Up @@ -438,7 +421,7 @@ export function unexpectedDirectiveLocationError(locationName: string): Error {
return new Error(`Fatal: Unknown directive location "${locationName}".`);
}

export function unexpectedTypeNodeKindError(childPath: string): Error {
export function unexpectedTypeNodeKindFatalError(childPath: string): Error {
return new Error(
`Fatal: Expected all constituent types of "${childPath}" to be one of the following: ` +
`"LIST_TYPE", "NAMED_TYPE", or "NON_NULL_TYPE".`,
Expand Down Expand Up @@ -881,10 +864,8 @@ export function allFieldDefinitionsAreInaccessibleError(typeString: string, type
);
}

export function equivalentSourceAndTargetOverrideError(subgraphName: string, hostPath: string): Error {
return new Error(
`Cannot override field "${hostPath}" because the source and target subgraph names are both "${subgraphName}"`,
);
export function equivalentSourceAndTargetOverrideErrorMessage(subgraphName: string, hostPath: string): string {
return `Cannot override field "${hostPath}" because the source and target subgraph names are both "${subgraphName}"`;
}

export function undefinedEntityInterfaceImplementationsError(
Expand Down
Loading

0 comments on commit 311b2fd

Please sign in to comment.