Skip to content

Commit

Permalink
rename serialize and parseValue methods (#4241)
Browse files Browse the repository at this point in the history
finish addressing #2357, started in #4218
  • Loading branch information
yaacovCR authored Oct 17, 2024
1 parent 858aa32 commit 44e5d9a
Show file tree
Hide file tree
Showing 16 changed files with 371 additions and 275 deletions.
4 changes: 2 additions & 2 deletions integrationTests/ts/kitchenSink-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Kind } from 'graphql/language';
// Test subset of public APIs with "exactOptionalPropertyTypes" flag enabled
new GraphQLScalarType({
name: 'SomeScalar',
serialize: undefined,
parseValue: undefined,
coerceOutputValue: undefined,
coerceInputValue: undefined,
coerceInputLiteral: undefined,
});

Expand Down
6 changes: 3 additions & 3 deletions src/execution/__tests__/executor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1258,10 +1258,10 @@ describe('Execute: Handles basic execution tasks', () => {
expect(asyncResult).to.deep.equal(result);
});

it('fails when serialize of custom scalar does not return a value', () => {
it('fails when coerceOutputValue of custom scalar does not return a value', () => {
const customScalar = new GraphQLScalarType({
name: 'CustomScalar',
serialize() {
coerceOutputValue() {
/* returns nothing */
},
});
Expand All @@ -1283,7 +1283,7 @@ describe('Execute: Handles basic execution tasks', () => {
errors: [
{
message:
'Expected `CustomScalar.serialize("CUSTOM_VALUE")` to return non-nullable value, returned: undefined',
'Expected `CustomScalar.coerceOutputValue("CUSTOM_VALUE")` to return non-nullable value, returned: undefined',
locations: [{ line: 1, column: 3 }],
path: ['customScalar'],
},
Expand Down
24 changes: 12 additions & 12 deletions src/execution/__tests__/variables-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const TestFaultyScalarGraphQLError = new GraphQLError(

const TestFaultyScalar = new GraphQLScalarType({
name: 'FaultyScalar',
parseValue() {
coerceInputValue() {
throw TestFaultyScalarGraphQLError;
},
coerceInputLiteral() {
Expand All @@ -54,13 +54,13 @@ const TestFaultyScalar = new GraphQLScalarType({

const TestComplexScalar = new GraphQLScalarType({
name: 'ComplexScalar',
parseValue(value) {
expect(value).to.equal('SerializedValue');
return 'DeserializedValue';
coerceInputValue(value) {
expect(value).to.equal('ExternalValue');
return 'InternalValue';
},
coerceInputLiteral(ast) {
expect(ast).to.include({ kind: 'StringValue', value: 'SerializedValue' });
return 'DeserializedValue';
expect(ast).to.include({ kind: 'StringValue', value: 'ExternalValue' });
return 'InternalValue';
},
});

Expand Down Expand Up @@ -284,13 +284,13 @@ describe('Execute: Handles inputs', () => {
it('properly runs coerceInputLiteral on complex scalar types', () => {
const result = executeQuery(`
{
fieldWithObjectInput(input: {c: "foo", d: "SerializedValue"})
fieldWithObjectInput(input: {c: "foo", d: "ExternalValue"})
}
`);

expect(result).to.deep.equal({
data: {
fieldWithObjectInput: '{ c: "foo", d: "DeserializedValue" }',
fieldWithObjectInput: '{ c: "foo", d: "InternalValue" }',
},
});
});
Expand Down Expand Up @@ -447,25 +447,25 @@ describe('Execute: Handles inputs', () => {
});

it('executes with complex scalar input', () => {
const params = { input: { c: 'foo', d: 'SerializedValue' } };
const params = { input: { c: 'foo', d: 'ExternalValue' } };
const result = executeQuery(doc, params);

expect(result).to.deep.equal({
data: {
fieldWithObjectInput: '{ c: "foo", d: "DeserializedValue" }',
fieldWithObjectInput: '{ c: "foo", d: "InternalValue" }',
},
});
});

it('errors on faulty scalar type input', () => {
const params = { input: { c: 'foo', e: 'SerializedValue' } };
const params = { input: { c: 'foo', e: 'ExternalValue' } };
const result = executeQuery(doc, params);

expectJSON(result).toDeepEqual({
errors: [
{
message:
'Variable "$input" got invalid value "SerializedValue" at "input.e"; FaultyScalarErrorMessage',
'Variable "$input" got invalid value "ExternalValue" at "input.e"; FaultyScalarErrorMessage',
locations: [{ line: 2, column: 16 }],
extensions: { code: 'FaultyScalarErrorExtensionCode' },
},
Expand Down
18 changes: 9 additions & 9 deletions src/execution/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ function toNodes(fieldDetailsList: FieldDetailsList): ReadonlyArray<FieldNode> {
* Implements the "Executing fields" section of the spec
* In particular, this function figures out the value that the field returns by
* calling its resolve function, then calls completeValue to complete promises,
* serialize scalars, or execute the sub-selection-set for objects.
* coercing scalars, or execute the sub-selection-set for objects.
*/
function executeField(
exeContext: ExecutionContext,
Expand Down Expand Up @@ -937,7 +937,7 @@ function handleFieldError(
* for the inner type on each item in the list.
*
* If the field type is a Scalar or Enum, ensures the completed value is a legal
* value of the type by calling the `serialize` method of GraphQL type
* value of the type by calling the `coerceOutputValue` method of GraphQL type
* definition.
*
* If the field is an abstract type, determine the runtime type of the value
Expand Down Expand Up @@ -1001,8 +1001,8 @@ function completeValue(
);
}

// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
// returning null if serialization is not possible.
// If field type is a leaf type, Scalar or Enum, coerce to a valid value,
// returning null if coercion is not possible.
if (isLeafType(returnType)) {
return [completeLeafValue(returnType, result), undefined];
}
Expand Down Expand Up @@ -1571,14 +1571,14 @@ function completeLeafValue(
returnType: GraphQLLeafType,
result: unknown,
): unknown {
const serializedResult = returnType.serialize(result);
if (serializedResult == null) {
const coerced = returnType.coerceOutputValue(result);
if (coerced == null) {
throw new Error(
`Expected \`${inspect(returnType)}.serialize(${inspect(result)})\` to ` +
`return non-nullable value, returned: ${inspect(serializedResult)}`,
`Expected \`${inspect(returnType)}.coerceOutputValue(${inspect(result)})\` to ` +
`return non-nullable value, returned: ${inspect(coerced)}`,
);
}
return serializedResult;
return coerced;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@ export type {
GraphQLUnionTypeExtensions,
GraphQLScalarSerializer,
GraphQLScalarValueParser,
/* @deprecated in favor of GraphQLScalarInputLiteralCoercer, will be removed in v18 */
GraphQLScalarLiteralParser,
GraphQLScalarOutputValueCoercer,
GraphQLScalarInputValueCoercer,
GraphQLScalarInputLiteralCoercer,
GraphQLDefaultValueUsage,
} from './type/index.js';
Expand Down
36 changes: 34 additions & 2 deletions src/type/__tests__/definition-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ describe('Type System: Scalars', () => {
serialize: someScalar.serialize,
parseValue: someScalar.parseValue,
parseLiteral: someScalar.parseLiteral,
coerceOutputValue: someScalar.coerceOutputValue,
coerceInputValue: someScalar.coerceInputValue,
coerceInputLiteral: undefined,
valueToLiteral: undefined,
extensions: {},
Expand All @@ -76,6 +78,8 @@ describe('Type System: Scalars', () => {
serialize: passThroughFunc,
parseValue: passThroughFunc,
parseLiteral: passThroughFunc,
coerceOutputValue: passThroughFunc,
coerceInputValue: passThroughFunc,
coerceInputLiteral: passThroughFunc,
valueToLiteral: passThroughFunc,
extensions: { someExtension: 'extension' },
Expand All @@ -95,6 +99,8 @@ describe('Type System: Scalars', () => {
serialize: passThroughFunc,
parseValue: passThroughFunc,
parseLiteral: passThroughFunc,
coerceOutputValue: passThroughFunc,
coerceInputValue: passThroughFunc,
coerceInputLiteral: passThroughFunc,
valueToLiteral: passThroughFunc,
extensions: { [test]: 'extension' },
Expand All @@ -110,6 +116,8 @@ describe('Type System: Scalars', () => {

expect(scalar.serialize).to.equal(identityFunc);
expect(scalar.parseValue).to.equal(identityFunc);
expect(scalar.coerceOutputValue).to.equal(identityFunc);
expect(scalar.coerceInputValue).to.equal(identityFunc);
expect(scalar.parseLiteral).to.be.a('function');
/* default will be provided in v18 when parseLiteral is removed */
// expect(scalar.coerceInputLiteral).to.be.a('function');
Expand Down Expand Up @@ -143,15 +151,15 @@ describe('Type System: Scalars', () => {
);
});

it('rejects a Scalar type defining coerceInputLiteral but not parseValue', () => {
it('rejects a Scalar type defining coerceInputLiteral but not coerceInputValue', () => {
expect(
() =>
new GraphQLScalarType({
name: 'SomeScalar',
coerceInputLiteral: passThroughFunc,
}),
).to.throw(
'SomeScalar must provide both "parseValue" and "coerceInputLiteral" functions.',
'SomeScalar must provide both "coerceInputValue" and "coerceInputLiteral" functions.',
);
});
});
Expand Down Expand Up @@ -644,6 +652,30 @@ describe('Type System: Enums', () => {
expect(someEnum.toConfig()).to.deep.equal(someEnumConfig);
});

it('can be coerced to an output value via serialize() method', () => {
const someEnum = new GraphQLEnumType({
name: 'SomeEnum',
values: {
FOO: {
value: 'foo',
},
},
});
expect(someEnum.serialize('foo')).to.equal('FOO');
});

it('can be coerced to an input value via parseValue() method', () => {
const someEnum = new GraphQLEnumType({
name: 'SomeEnum',
values: {
FOO: {
value: 'foo',
},
},
});
expect(someEnum.parseValue('FOO')).to.equal('foo');
});

it('defines an enum type with deprecated value', () => {
const EnumTypeWithDeprecatedValue = new GraphQLEnumType({
name: 'EnumWithDeprecatedValue',
Expand Down
Loading

0 comments on commit 44e5d9a

Please sign in to comment.