从 .gql 文件中命名导出多个 graphql 操作

Posted

技术标签:

【中文标题】从 .gql 文件中命名导出多个 graphql 操作【英文标题】:Named export multiple graphql operation from .gql files 【发布时间】:2021-01-11 00:15:46 【问题描述】:

我在.gql 文件中定义了一些操作(查询/变异,有时还有文件底部的一些片段),有时在一个文件中定义了多个。

我想将这些导入到我的 JS/TS 文件中,可能还会为 TypeScript 生成相应的类型。

我在这里设置了一个 3 个文件的例子:

https://gist.github.com/balazsorban44/352d5295f604fb4274bfc934937737a1

queries.gql 文件是源文件。它们应该在文件中生成相应的模块类型(参见generated-types.d.ts),因此我可以将它们导入我的index.ts 文件并使用它通过简单的fetch 进行graphql 调用。

到目前为止,我尝试过的是这些工具/包:

graphql-tag/loader webpack-graphql-loader graphql-raw-loader

据我所知,以上这些都不支持将每个文件导出为字符串的多个操作,仅支持作为 DocumentNode 的多个操作,或者将整个文件作为字符串。

graphql-codegen/typescript-graphql-files-modules 仅输出 DocumentNode 类型,没有将类型更改为字符串的选项

如果还有其他问题,请告诉我。

【问题讨论】:

【参考方案1】:

使用graphql-tools 中的documents-loading 和separateOperations 的解决方案 - 用于拆分 AST 的实用函数。步骤如下:

    .gql文件加载文档 将这个包罗万象的 AST 分成单独的 AST,这些 AST 代表可以单独发送到服务器的每个操作。 使用graphql 包的print 函数将DocumentNode(AST) 转换为字符串。

例如

queries.gql:

query Something 
  name
  id


query SomethingElse($email: String!) 
  somethingelse(email: $email) 
    phone
    ...SomeFragment
  


fragment SomeFragment on User 
  email
  address

index.ts:

import  loadDocumentsSync  from '@graphql-tools/load';
import  GraphQLFileLoader  from '@graphql-tools/graphql-file-loader';
import path from 'path';
import  separateOperations, print, buildSchema  from 'graphql';
import express from 'express';
import  graphqlHTTP  from 'express-graphql';
import fetch from 'node-fetch';

const documents = loadDocumentsSync(path.resolve(__dirname, './queries.gql'), 
  loaders: [new GraphQLFileLoader()],
);
const  Something, SomethingElse  = separateOperations(documents[0].document!);

console.log(print(Something));
console.log(print(SomethingElse));

// server
const schema = buildSchema(`
  type User 
    id: ID!
    name: String
    email: String
    address: String
    phone: String
  
  type Query 
    somethingelse(email: String!): User
    Something: User
  
`);
const root = 
  somethingelse( email ) 
    return  id: 1, name: 'teresa teng', email, address: 'Japan', phone: '123' ;
  ,
;
const app = express();
app.use(
  '/graphql',
  graphqlHTTP(
    schema: schema,
    rootValue: root,
    graphiql: true,
  ),
);
app.listen(4000, () => console.log('graphql server running on localhost 4000'));

// test
fetch('http://localhost:4000/graphql', 
  method: 'POST',
  headers: 
    'Content-Type': 'application/json',
  ,
  body: JSON.stringify( query: print(SomethingElse), variables:  email: 'teresa.teng@gmail.com'  ),
)
  .then((res) => res.json())
  .then((res) => console.log(res))
  .catch(console.error);

执行结果:

query Something 
  name
  id


query SomethingElse($email: String!) 
  somethingelse(email: $email) 
    phone
    ...SomeFragment
  


fragment SomeFragment on User 
  email
  address


graphql server running on localhost 4000
 data:
    somethingelse:
       phone: '123',
        email: 'teresa.teng@gmail.com',
        address: 'Japan'   

顺便说一句,如果您提供的工具/包可以从.gql 文件加载文档,您可以使用它而不是使用graphql-tools。其余步骤相同。

【讨论】:

以上是关于从 .gql 文件中命名导出多个 graphql 操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 apollo 的 graphql-gql 中使用从 npm 包导入的自定义 graphQL 类型

GraphQL 代码生成器 - 无法从 Nestjs 服务器端点加载我的 GQL 架构

为啥 WebStorm 在 Vue 组件或 .graphql 文件中的 apollo 对象内的 gql 查询中显示错误

在 Gatsby 中的 JSX 组件之外进行 graphql 查询

在 apollo graphql 的单个 useEffect 挂钩中使用多个查询

在 NestJS + GraphQL 中实现“命名空间类型”解析器