web-dev-qa-db-ja.com

apollo-clientはnode.jsで動作しますか?

いくつかのテストといくつかのデータマッシュアップのために、graphqlクライアントlib node.jsで実行するが必要です-本番環境ではありません。他の場所ではアポロを使用しています(react-apollo、アポロのgraphql-server-express)。私のニーズはかなり単純です。

apollo-client実行可能な選択肢ですか? nodeでの使用例やドキュメントは見つかりません。気づいたら、共有してください。

または、ノードでリファレンスgraphqlクライアントを使用する必要がありますか?

28
Ed Staub

Apolloクライアントはノード上で問題なく動作するはずです。 cross-fetch をインストールする必要があるのは、fetchが存在することを前提としているためです。

以下は、Node.jsで動作するApolloクライアントの完全なTypeScript実装です。

import ApolloClient from "apollo-boost";
import gql from "graphql-tag";
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));
11
André Pena

誰かが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);
})

ここに単純なノードのjs実装があります。

「graphiql」クライアントは、開発活動には十分です。

1. run npm install
2. start server with "node server.js"
3. hit "http://localhost:8080/graphiql"  for graphiql client

server.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
});
2
sarang

@YakirNaのコメントに応じて:

私が説明した他のニーズについて話すことはできませんが、かなりの量のテストを行いました。私はすべてのテストをインプロセスで行うことになりました。

ほとんどのテストはリゾルバーテストになります。これは、graphqlライブラリのgraphql関数をテストクエリで呼び出し、応答を検証するジグを介して行います。

また、Expressのhttp処理レベルで機能する(ほぼ)エンドツーエンドのテストレイヤーもあります。偽のHTTPリクエストを作成し、プロセス内の応答を検証します。これはすべてサーバープロセス内にあります。何もネットワーク上を行きません。私はこれを軽く使用しますが、主にJWT認証と、graphqlリクエストボディから独立したその他のリクエストレベルの動作をテストするために使用します。

1
Ed Staub

同じ質問に遭遇しました。グラフQLから最終的なフロントエンドアプリケーションにデータを準備するためのミドルウェアサービスを作成したかったためです。

  • 最適化されたデータ表現(および標準出力データインターフェイス)
  • より速い応答時間

graphQLサーバーは外部プロバイダーによって提供され、データモデルに対する所有権はなく、GQLを直接使用すると仮定します。

したがって、React/Angular、Vuejs ...のようなフロントエンドフレームワークにGraphQL Apolloclientを直接実装したくありませんでしたが、REST API。

これは、(TypeScriptを使用して)アセンブルできた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にフェッチを注入する必要がありました

  • 外部プロバイダーのgraphQLエンドポイントにアクセスするためにAuthorizationヘッダーを設定する必要がありました

  • クエリでFragmentsを使用するためにIntrospectionFragmentMatcherを使用し、スキーマタイプを構築しました( "fragmentTypes.json"とinitスクリプト)

これを投稿して、私の経験を追加し、質問の情報を追加します。また、このラッパーのコメントと改善点を楽しみにしています。

0
koalaok