44

我需要一个 graphql 客户端库来在 node.js 上运行以进行一些测试和一些数据混搭——而不是生产能力。我在其他任何地方都使用阿波罗(react-apollo,阿波罗的graphql-server-express)。我的需求很简单。

apollo-client一个可行的选择吗?我找不到在节点上使用它的示例或文档 - 如果您知道,请分享。

或者也许我应该/可以在节点上使用参考 graphql 客户端?

4

7 回答 7

42

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));
于 2019-02-22T22:40:34.167 回答
15

较新的 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}`))
于 2020-06-15T14:04:07.853 回答
8

如果有人正在寻找 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);
})
于 2019-03-04T19:06:29.913 回答
6

你可以让 apollo-client 工作,但这不是这个用例的最佳选择。

请改用graphql-request

最小的 GraphQL 客户端,支持脚本或简单应用程序的节点和浏览器

每个 npmjs 的功能:

  • 最简单和轻量级的 GraphQL 客户端
  • 基于 Promise 的 API(与 async / await 一起使用)
  • 打字稿支持
  • 同构(适用于节点/浏览器)

例子:

    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))

我与这个包没有任何关系。

于 2020-09-03T21:59:59.013 回答
1

这是简单的节点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
});
于 2016-11-25T06:55:35.563 回答
1

回应@YakirNa 的评论:

我无法谈论我描述的其他需求,但我已经做了相当多的测试。我最终在进行中进行了所有测试。

大多数测试最终都是解析器测试,我通过一个夹具来完成,该夹具graphql使用测试查询调用 graphql 库的函数,然后验证响应。

我还有一个(几乎)端到端的测试层,可以在 express 的 http 处理级别上工作。它创建一个虚假的 HTTP 请求并在进程中验证响应。这一切都在服务器进程中;没有任何东西通过电线。我轻轻地使用它,主要用于测试 JWT 身份验证和其他独立于 graphql 请求主体的请求级行为。

于 2017-07-27T22:41:16.807 回答
0

我遇到了同样的问题,因为我想创建一个中间件服务来准备从 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”)

发布这个只是为了增加我的经验,也许还有更多关于这个问题的信息。也期待对此包装器的评论和改进点。

于 2020-03-14T11:11:30.467 回答