Skip to content

Error handling #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 5, 2025
200 changes: 100 additions & 100 deletions src/utilities/resolveSchemaCoordinate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,84 +98,24 @@ export function resolveSchemaCoordinate(
);
}

/**
* SchemaCoordinate : @ Name
*/
function resolveDirectiveCoordinate(
schema: GraphQLSchema,
schemaCoordinate: DirectiveCoordinateNode,
): ResolvedDirective | undefined {
// Let {directiveName} be the value of the first {Name}.
const directiveName = schemaCoordinate.name.value;

// Let {directive} be the directive in the {schema} named {directiveName}.
const directive = schema.getDirective(directiveName);

// If {directive} does not exist, return undefined.
if (!directive) {
return;
}

// Otherwise return the directive in the {schema} named {directiveName}.
return { kind: 'Directive', directive };
}

/**
* SchemaCoordinate : @ Name ( Name : )
*/
function resolveDirectiveArgumentCoordinate(
schema: GraphQLSchema,
schemaCoordinate: DirectiveArgumentCoordinateNode,
): ResolvedDirectiveArgument | undefined {
// Let {directiveName} be the value of the first {Name}.
const directiveName = schemaCoordinate.name.value;

// Let {directive} be the directive in the {schema} named {directiveName}.
const directive = schema.getDirective(directiveName);

// Assert that {directive} exists.
if (!directive) {
throw new Error(
`Expected ${inspect(directiveName)} to be defined as a directive in the schema.`,
);
}

// Let {directiveArgumentName} be the value of the second {Name}.
const {
argumentName: { value: directiveArgumentName },
} = schemaCoordinate;
const directiveArgument = directive.args.find(
(arg) => arg.name === directiveArgumentName,
);

// If {directiveArgumentName} does not exist, return undefined.
if (!directiveArgument) {
return;
}

// Return the argument of {directive} named {directiveArgumentName}.
return { kind: 'DirectiveArgument', directive, directiveArgument };
}

/**
* SchemaCoordinate : Name
*/
function resolveTypeCoordinate(
schema: GraphQLSchema,
schemaCoordinate: TypeCoordinateNode,
): ResolvedNamedType | undefined {
// Let {typeName} be the value of the first {Name}.
// 1. Let {typeName} be the value of the first {Name}.
// 2. Let {type} be the type in the {schema} named {typeName}.
const typeName = schemaCoordinate.name.value;

// Let {type} be the type in the {schema} named {typeName}.
const type = schema.getType(typeName);

// If {type} does not exist, return undefined.
// 3. If {type} does not exist, return {void}.
if (!type) {
return;
}

// Return the type in the {schema} named {typeName}.
// 4. {type}
return { kind: 'NamedType', type };
}

Expand All @@ -186,66 +126,69 @@ function resolveMemberCoordinate(
schema: GraphQLSchema,
schemaCoordinate: MemberCoordinateNode,
): ResolvedField | ResolvedInputField | ResolvedEnumValue | undefined {
// Let {typeName} be the value of the first {Name}.
// 1. Let {typeName} be the value of the first {Name}.
// 2. Let {type} be the type in the {schema} named {typeName}.
const typeName = schemaCoordinate.name.value;

// Let {type} be the type in the {schema} named {typeName}.
const type = schema.getType(typeName);

// Assert that {type} exists.
// 3. Assert that {type} exists.
if (!type) {
throw new Error(
`Expected ${inspect(typeName)} to be defined as a type in the schema.`,
);
}

const memberName = schemaCoordinate.memberName.value;

// If {type} is an Enum type:
// 4. If {type} is an Enum type:
if (isEnumType(type)) {
// Let {enumValueName} be the value of the second {Name}.
const enumValue = type.getValue(memberName);
// 5. Let {enumValueName} be the value of the second {Name}.
// 6. Let {enumValue} be the enum value of {type} named {enumValueName}.
const enumValueName = schemaCoordinate.memberName.value;
const enumValue = type.getValue(enumValueName);

// TODO: Add a spec line about returning undefined if the member name does not exist.
// 7. If {enumValue} does not exist, return {void}.
if (enumValue == null) {
return;
}

// Return the enum value of {type} named {enumValueName}.
// 8. Return {enumValue}
return { kind: 'EnumValue', type, enumValue };
}

// Otherwise if {type} is an Input Object type:
// 9. Otherwise if {type} is an Input Object type:
if (isInputObjectType(type)) {
// Let {inputFieldName} be the value of the second {Name}.
const inputField = type.getFields()[memberName];
// 10. Let {inputFieldName} be the value of the second {Name}.
// 11. Let {inputField} be the input field of {type} named {inputFieldName}.
const inputFieldName = schemaCoordinate.memberName.value;
const inputField = type.getFields()[inputFieldName];

// TODO: Add a spec line about returning undefined if the member name does not exist.
// 12. If {inputField} does not exist, return {void}.
if (inputField == null) {
return;
}

// Return the input field of {type} named {inputFieldName}.
// 13. Return {inputField}
return { kind: 'InputField', type, inputField };
}

// Otherwise:
// Assert {type} must be an Object or Interface type.
// 14. Otherwise:
// 15. Assert {type} must be an Object or Interface type.
if (!isObjectType(type) && !isInterfaceType(type)) {
throw new Error(
`Expected ${inspect(typeName)} to be an object type, interface type, input object type, or enum type.`,
);
}

// Let {fieldName} be the value of the second {Name}.
const field = type.getFields()[memberName];
// 16. Let {fieldName} be the value of the second {Name}.
// 17. Let {field} be the field of {type} named {fieldName}.
const fieldName = schemaCoordinate.memberName.value;
const field = type.getFields()[fieldName];

// TODO: Add a spec line about returning undefined if the member name does not exist.
// 18. If {field} does not exist, return {void}.
if (field == null) {
return;
}

// Return the field of {type} named {fieldName}.
// 19. Return {field}
return { kind: 'Field', type, field };
}

Expand All @@ -256,54 +199,111 @@ function resolveArgumentCoordinate(
schema: GraphQLSchema,
schemaCoordinate: ArgumentCoordinateNode,
): ResolvedFieldArgument | undefined {
// Let {typeName} be the value of the first {Name}.
// 1. Let {typeName} be the value of the first {Name}.
// 2. Let {type} be the type in the {schema} named {typeName}.
const typeName = schemaCoordinate.name.value;

// Let {type} be the type in the {schema} named {typeName}.
const type = schema.getType(typeName);

// Assert that {type} exists.
if (!type) {
// 3. Assert that {type} exists.
if (type == null) {
throw new Error(
`Expected ${inspect(typeName)} to be defined as a type in the schema.`,
);
}

const fieldName = schemaCoordinate.fieldName.value;

// Assert {type} must be an Object or Interface type.
// 4. Assert {type} must be an Object or Interface type.
if (!isObjectType(type) && !isInterfaceType(type)) {
throw new Error(
`Expected ${inspect(typeName)} to be an object type or interface type.`,
);
}

// Let {fieldName} be the value of the second {Name}.
// Let {field} be the field of {type} named {fieldName}.
// 5. Let {fieldName} be the value of the second {Name}.
// 6. Let {field} be the field of {type} named {fieldName}.
const fieldName = schemaCoordinate.fieldName.value;
const field = type.getFields()[fieldName];

// Assert {field} must exist.
// 7. Assert {field} must exist.
if (field == null) {
throw new Error(
`Expected ${inspect(fieldName)} to exist as a field of type ${inspect(typeName)} in the schema.`,
);
}

// Let {fieldArgumentName} be the value of the third {Name}.
// 8. Let {fieldArgumentName} be the value of the third {Name}.
// 9. Let {fieldArgument} be the argument of {field} named {fieldArgumentName}.
const fieldArgumentName = schemaCoordinate.argumentName.value;
const fieldArgument = field.args.find(
(arg) => arg.name === fieldArgumentName,
);

// TODO: Add a spec line about returning undefined if the argument does not exist.
// 10. If {fieldArgument} does not exist, return {void}.
if (fieldArgument == null) {
return;
}

// Return the argument of {field} named {fieldArgumentName}.
// 11. Return {fieldArgument}.
return { kind: 'FieldArgument', type, field, fieldArgument };
}

/**
* SchemaCoordinate : @ Name
*/
function resolveDirectiveCoordinate(
schema: GraphQLSchema,
schemaCoordinate: DirectiveCoordinateNode,
): ResolvedDirective | undefined {
// 1. Let {directiveName} be the value of the first {Name}.
// 2. Let {directive} be the directive in the {schema} named {directiveName}.
const directiveName = schemaCoordinate.name.value;
const directive = schema.getDirective(directiveName);

// 3. If {directive} does not exist, return {void}.
if (!directive) {
return;
}

// 4. Otherwise return {directive}.
return { kind: 'Directive', directive };
}

/**
* SchemaCoordinate : @ Name ( Name : )
*/
function resolveDirectiveArgumentCoordinate(
schema: GraphQLSchema,
schemaCoordinate: DirectiveArgumentCoordinateNode,
): ResolvedDirectiveArgument | undefined {
// 1. Let {directiveName} be the value of the first {Name}.
// 2. Let {directive} be the directive in the {schema} named {directiveName}.
const directiveName = schemaCoordinate.name.value;
const directive = schema.getDirective(directiveName);

// 3. Assert {directive} must exist.
if (!directive) {
throw new Error(
`Expected ${inspect(directiveName)} to be defined as a directive in the schema.`,
);
}

// 4. Let {directiveArgumentName} be the value of the second {Name}.
// 5. Let {directiveArgument} be the argument of {directive} named {directiveArgumentName}.
const {
argumentName: { value: directiveArgumentName },
} = schemaCoordinate;
const directiveArgument = directive.args.find(
(arg) => arg.name === directiveArgumentName,
);

// 6. If {directiveArgument} does not exist, return {void}.
if (!directiveArgument) {
return;
}

// 7. Return {directiveArgument}.
return { kind: 'DirectiveArgument', directive, directiveArgument };
}

/**
* Resolves schema coordinate from a parsed SchemaCoordinate node.
*/
Expand Down
Loading