我需要一个 graphql 客户端库来在 node.js 上运行以进行一些测试和一些数据混搭——而不是生产能力。我在其他任何地方都使用阿波罗(react-apollo
,阿波罗的graphql-server-express
)。我的需求很简单。
是apollo-client
一个可行的选择吗?我找不到在节点上使用它的示例或文档 - 如果您知道,请分享。
或者也许我应该/可以在节点上使用参考 graphql 客户端?
我需要一个 graphql 客户端库来在 node.js 上运行以进行一些测试和一些数据混搭——而不是生产能力。我在其他任何地方都使用阿波罗(react-apollo
,阿波罗的graphql-server-express
)。我的需求很简单。
是apollo-client
一个可行的选择吗?我找不到在节点上使用它的示例或文档 - 如果您知道,请分享。
或者也许我应该/可以在节点上使用参考 graphql 客户端?
Apollo Client 应该可以在 Node.js 上正常工作。您只需要安装交叉提取,因为它假定fetch
存在。
这是在 Node.js 上工作的 Apollo 客户端的完整 TypeScript 实现。
import ApolloClient, { gql } from "apollo-boost";
import { InsertJob } from "./graphql-types";
import 'cross-fetch/polyfill';
const client = new ApolloClient({
uri: "http://localhost:3000/graphql"
});
client.mutate<InsertJob.AddCompany, InsertJob.Variables>({
mutation: gql`mutation insertJob($companyName: String!) {
addCompany(input: { displayName: $companyName } ) {
id
}
}`,
variables: {
companyName: "aaa"
}
})
.then(result => console.log(result));
较新的 Apollo 版本提供了一种更简单的方法来执行此操作,如Apollo 文档中所述,请查看“独立”部分。基本上可以简单地使用ApolloLink
以执行查询或突变。
以下是撰写本文时文档中示例代码的副本,node-fetch
用法为 config 到createHttpLink
. 查看文档以获取有关如何使用这些工具的更多详细信息。
import { execute, makePromise } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import gql from 'graphql-tag';
import fetch from 'node-fetch';
const uri = 'http://localhost:4000/graphql';
const link = createHttpLink({ uri, fetch });
const operation = {
query: gql`query { hello }`,
variables: {} //optional
operationName: {} //optional
context: {} //optional
extensions: {} //optional
};
// execute returns an Observable so it can be subscribed to
execute(link, operation).subscribe({
next: data => console.log(`received data: ${JSON.stringify(data, null, 2)}`),
error: error => console.log(`received error ${error}`),
complete: () => console.log(`complete`),
})
// For single execution operations, a Promise can be used
makePromise(execute(link, operation))
.then(data => console.log(`received data ${JSON.stringify(data, null, 2)}`))
.catch(error => console.log(`received error ${error}`))
如果有人正在寻找 JavaScript 版本:
require('dotenv').config();
const gql = require('graphql-tag');
const ApolloClient = require('apollo-boost').ApolloClient;
const fetch = require('cross-fetch/polyfill').fetch;
const createHttpLink = require('apollo-link-http').createHttpLink;
const InMemoryCache = require('apollo-cache-inmemory').InMemoryCache;
const client = new ApolloClient({
link: createHttpLink({
uri: process.env.API,
fetch: fetch
}),
cache: new InMemoryCache()
});
client.mutate({
mutation: gql`
mutation popJob {
popJob {
id
type
param
status
progress
creation_date
expiration_date
}
}
`,
}).then(job => {
console.log(job);
})
你可以让 apollo-client 工作,但这不是这个用例的最佳选择。
请改用graphql-request。
最小的 GraphQL 客户端,支持脚本或简单应用程序的节点和浏览器
每个 npmjs 的功能:
例子:
import { request, gql } from 'graphql-request'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
request('https://api.graph.cool/simple/v1/movies', query).then((data) => console.log(data))
我与这个包没有任何关系。
这是简单的节点js实现。
'graphiql' 客户端对于开发活动来说已经足够好了。
1. run npm install
2. start server with "node server.js"
3. hit "http://localhost:8080/graphiql" for graphiql client
服务器.js
var graphql = require ('graphql').graphql
var express = require('express')
var graphQLHTTP = require('express-graphql')
var Schema = require('./schema')
// This is just an internal test
var query = 'query{starwar{name, gender,gender}}'
graphql(Schema, query).then( function(result) {
console.log(JSON.stringify(result,null," "));
});
var app = express()
.use('/', graphQLHTTP({ schema: Schema, pretty: true, graphiql: true }))
.listen(8080, function (err) {
console.log('GraphQL Server is now running on localhost:8080');
});
schema.js
//schema.js
var graphql = require ('graphql');
var http = require('http');
var StarWar = [
{
"name": "default",
"gender": "default",
"mass": "default"
}
];
var TodoType = new graphql.GraphQLObjectType({
name: 'starwar',
fields: function () {
return {
name: {
type: graphql.GraphQLString
},
gender: {
type: graphql.GraphQLString
},
mass: {
type: graphql.GraphQLString
}
}
}
});
var QueryType = new graphql.GraphQLObjectType({
name: 'Query',
fields: function () {
return {
starwar: {
type: new graphql.GraphQLList(TodoType),
resolve: function () {
return new Promise(function (resolve, reject) {
var request = http.get({
hostname: 'swapi.co',
path: '/api/people/1/',
method: 'GET'
}, function(res){
res.setEncoding('utf8');
res.on('data', function(response){
StarWar = [JSON.parse(response)];
resolve(StarWar)
console.log('On response success:' , StarWar);
});
});
request.on('error', function(response){
console.log('On error' , response.message);
});
request.end();
});
}
}
}
}
});
module.exports = new graphql.GraphQLSchema({
query: QueryType
});
回应@YakirNa 的评论:
我无法谈论我描述的其他需求,但我已经做了相当多的测试。我最终在进行中进行了所有测试。
大多数测试最终都是解析器测试,我通过一个夹具来完成,该夹具graphql
使用测试查询调用 graphql 库的函数,然后验证响应。
我还有一个(几乎)端到端的测试层,可以在 express 的 http 处理级别上工作。它创建一个虚假的 HTTP 请求并在进程中验证响应。这一切都在服务器进程中;没有任何东西通过电线。我轻轻地使用它,主要用于测试 JWT 身份验证和其他独立于 graphql 请求主体的请求级行为。
我遇到了同样的问题,因为我想创建一个中间件服务来准备从 graphQL 到最终前端应用程序的数据,以便:
假设 graphQL 服务器由外部提供者提供,因此直接使用 GQL 对数据模型没有所有权
所以我不想直接在 React / Angular、Vuejs 等前端框架中实现 GraphQL Apolloclient ......而是通过 REST API 后端的 Nodejs 管理查询。
所以这是我能够组装的 Apolloclient 的类包装器(使用打字稿):
import ApolloClient from "apollo-client";
import { ApolloLink } from 'apollo-link'
import { HttpLink } from 'apollo-link-http'
import { onError } from 'apollo-link-error'
import fetch from 'node-fetch'
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
import introspectionQueryResultData from '../../fragmentTypes.json';
import { AppConfig } from 'app-config';
const config: AppConfig = require('../../../appConfig.js');
export class GraphQLQueryClient {
protected apolloClient: any;
constructor(headers: { [name: string]: string }) {
const api: any = {
spaceId: config.app.spaceId,
environmentId: config.app.environmentId,
uri: config.app.uri,
cdnApiPreviewToken: config.cdnApiPreviewToken,
};
// console.log(JSON.stringify(api));
const ACCESS_TOKEN = api.cdnApiPreviewToken;
const uri = api.uri;
console.log(`Apollo client setup to query uri: ${uri}`);
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
});
this.apolloClient = new ApolloClient({
link: ApolloLink.from([
onError(({ graphQLErrors, networkError }:any) => {
if (graphQLErrors) {
graphQLErrors.map((el:any) =>
console.warn(
el.message || el
)
)
graphQLErrors.map(({ message, locations, path }:any) =>
console.warn(
`[GraphQL error - Env ${api.environmentId}]: Message: ${message}, Location: ${JSON.stringify(locations)}, Path: ${path}`
)
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
}),
new HttpLink({
uri,
credentials: 'same-origin',
headers: {
Authorization: `Bearer ${ACCESS_TOKEN}`
},
fetch
})
]),
cache: new InMemoryCache({ fragmentMatcher }),
// fetchPolicy as network-only avoids using the cache.
defaultOptions: {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
});
}
}
在这个构造函数之后,我运行如下查询:
let response = await this.apolloClient.query({ query: gql`${query}` });
您可能已经注意到:
我需要在 Httplink 上注入 fetch
我必须设置授权标头才能访问外部提供者 graphQL 端点
我使用 IntrospectionFragmentMatcher 以便在我的查询中使用 Fragments,以及构建模式类型(带有 init 脚本的“fragmentTypes.json”)
发布这个只是为了增加我的经验,也许还有更多关于这个问题的信息。也期待对此包装器的评论和改进点。