GraphQL 不调用自定义标量方法
GraphQL not calling custom scalar methods
与其他许多人一样,我正在尝试使用 GraphQL 和 JavaScript 创建自己的 Date
标量。我已经阅读了很多示例并特别遵循 this guide from apollo。
我做了什么
- 已将
scalar Date
添加到我的架构中
- 使用我的序列化、parseValue 和 parseLiteral 实现创建了一个
GraphQLScalarType
的实例。我称那个实例为 dateScalar
- 向名为
Date
的解析器映射添加了一个新的 属性,其值为 dateScalar
这应该使我的 Date
准备好根据我读过的内容使用。但是,我每次执行查询时得到的值与我存储在数据库中的值完全相同。如果那是一个字符串,我会看到一个字符串,如果那是一个数字,我会看到一个数字。它在任何时候都不会被解析或序列化。
这是我的文件的样子。
schema.js
const { buildSchema } = require('graphql');
const schema = buildSchema(`
scalar Date
# more schema
`);
module.exports = schema;
root.js
const { dateScalar } = require('./customScalars');
const root = {
// queries
// mutations
// scalars
Date: dateScalar
};
module.exports = root;
customScalars.js
const { GraphQLScalarType } = require('graphql');
const dateScalar = new GraphQLScalarType({
name: 'Date',
description: 'This is a scalar version of the js Date',
serialize(value) {
console.log('call serialize');
return value.getTime();
},
parseValue(value) {
console.log('call parseValue');
return new Date(value).getFullYear();
},
parseLiteral(ast) {
console.log('call parseLiteral');
return;
}
});
module.exports = {
dateScalar
};
server.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./graphql/schema.js');
const graphqlRoot = require('./graphql/root.js');
var app = express();
app.use('/endpoint', graphqlHTTP({
schema: schema,
graphiql: true,
rootValue: graphqlRoot,
}));
app.listen(3333, () => console.log('Now browse to localhost:3333/endpoint'));
到目前为止我的调试
- 我已经在方法
serialize
等上使用了日志,其中 none 被调用了。
- 我已经从根目录中删除了
Date
属性,行为完全相同
- 我已经检查过
dateScalar
的实例是否符合我的预期。我通过在将其导入不同文件后调用 console.log(dateScalar.serialize(new Date().getTime()))
来完成此操作。执行此操作时,我得到的日志告诉我调用了序列化,结果正是我所期望的。
从根本上看,它似乎从未将我的架构中的标量与我的自定义标量实例相关联。也许我在这里做错了什么?
我的猜测是 GraphQL 正在使用 .toString()
进行序列化和解析,因为它没有找到我对 serializing/parsing.
的实现
关于如何让 GraphQL 使用我的自定义标量有什么想法吗?
tl;博士
使用 graphql-tools
制作可执行模式并使用 apollo-server-express
而不是 express-graphql
很遗憾,我不熟悉 express-graphql
。所以我的解决方案需要用 apollo-server-express
替换它。幸运的是,它不需要太多更改。
我做了一些修改以匹配您的代码,这对我有用。
首先安装软件包:
npm install apollo-server-express graphql-tools
代码如下:
const {makeExecutableSchema} = require('graphql-tools')
const {graphqlExpress} = require('apollo-server-express');
const graphqlRoot = require('./graphql/root.js');
//...
const schemaDef = `
scalar Date
# more schema
`;
//build the schema
const schema = makeExecutableSchema({
typeDefs: [schemaDef],
resolvers: graphqlRoot
});
// your new endpoint:
app.use('/endpoint', bodyParser.json(), graphqlExpress({ schema }));
阅读更多关于 Adding a GraphQL endpoint
此外,使用 Apollo 可以轻松拥有多个模式文件和解析器文件,而不必担心手动组合它们。这是文档中的解释:Modularizing the schema
与其他许多人一样,我正在尝试使用 GraphQL 和 JavaScript 创建自己的 Date
标量。我已经阅读了很多示例并特别遵循 this guide from apollo。
我做了什么
- 已将
scalar Date
添加到我的架构中 - 使用我的序列化、parseValue 和 parseLiteral 实现创建了一个
GraphQLScalarType
的实例。我称那个实例为dateScalar
- 向名为
Date
的解析器映射添加了一个新的 属性,其值为dateScalar
这应该使我的 Date
准备好根据我读过的内容使用。但是,我每次执行查询时得到的值与我存储在数据库中的值完全相同。如果那是一个字符串,我会看到一个字符串,如果那是一个数字,我会看到一个数字。它在任何时候都不会被解析或序列化。
这是我的文件的样子。
schema.js
const { buildSchema } = require('graphql');
const schema = buildSchema(`
scalar Date
# more schema
`);
module.exports = schema;
root.js
const { dateScalar } = require('./customScalars');
const root = {
// queries
// mutations
// scalars
Date: dateScalar
};
module.exports = root;
customScalars.js
const { GraphQLScalarType } = require('graphql');
const dateScalar = new GraphQLScalarType({
name: 'Date',
description: 'This is a scalar version of the js Date',
serialize(value) {
console.log('call serialize');
return value.getTime();
},
parseValue(value) {
console.log('call parseValue');
return new Date(value).getFullYear();
},
parseLiteral(ast) {
console.log('call parseLiteral');
return;
}
});
module.exports = {
dateScalar
};
server.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./graphql/schema.js');
const graphqlRoot = require('./graphql/root.js');
var app = express();
app.use('/endpoint', graphqlHTTP({
schema: schema,
graphiql: true,
rootValue: graphqlRoot,
}));
app.listen(3333, () => console.log('Now browse to localhost:3333/endpoint'));
到目前为止我的调试
- 我已经在方法
serialize
等上使用了日志,其中 none 被调用了。 - 我已经从根目录中删除了
Date
属性,行为完全相同 - 我已经检查过
dateScalar
的实例是否符合我的预期。我通过在将其导入不同文件后调用console.log(dateScalar.serialize(new Date().getTime()))
来完成此操作。执行此操作时,我得到的日志告诉我调用了序列化,结果正是我所期望的。
从根本上看,它似乎从未将我的架构中的标量与我的自定义标量实例相关联。也许我在这里做错了什么?
我的猜测是 GraphQL 正在使用 .toString()
进行序列化和解析,因为它没有找到我对 serializing/parsing.
关于如何让 GraphQL 使用我的自定义标量有什么想法吗?
tl;博士
使用 graphql-tools
制作可执行模式并使用 apollo-server-express
而不是 express-graphql
很遗憾,我不熟悉 express-graphql
。所以我的解决方案需要用 apollo-server-express
替换它。幸运的是,它不需要太多更改。
我做了一些修改以匹配您的代码,这对我有用。
首先安装软件包:
npm install apollo-server-express graphql-tools
代码如下:
const {makeExecutableSchema} = require('graphql-tools')
const {graphqlExpress} = require('apollo-server-express');
const graphqlRoot = require('./graphql/root.js');
//...
const schemaDef = `
scalar Date
# more schema
`;
//build the schema
const schema = makeExecutableSchema({
typeDefs: [schemaDef],
resolvers: graphqlRoot
});
// your new endpoint:
app.use('/endpoint', bodyParser.json(), graphqlExpress({ schema }));
阅读更多关于 Adding a GraphQL endpoint
此外,使用 Apollo 可以轻松拥有多个模式文件和解析器文件,而不必担心手动组合它们。这是文档中的解释:Modularizing the schema