在这篇文章中,我们将通过以下几个部分,比较Pothos和TypeGraphQL这两个模式构建器如何帮助开发者为其服务构建GraphQL模式--以及如何使用TypeScript与这些工具实际构建模式。
在文章的最后,我们将比较两个工具所提供的功能和一些使用案例。
关于GraphQL模式构建的入门知识
GraphQL模式由对象类型组成,其字段指定了它们可以接受的数据类型。这些类型被称为标量类型,它们被构建在SDL核心中。一旦我们定义了GraphQL模式,只有在具有各自类型的对象中定义的指定字段可以被查询或修改。
在GraphQL模式中,我们必须在创建模式的时候定义我们的查询和突变类型,除了突变类型,这并不总是强制性的。这两种类型的定义定义了我们根据预定义模式对GraphQL服务或API进行的每一次查询的入口点。你可以在博客的其他地方阅读更多关于GraphQL中的模式构建。
什么是Pothos?
Pothos是一个插件,它提供了一种简单的方法来创建和构建GraphQL和TypeScript的模式。
由于它是基于TS的,Pothos为GraphQL模式的构建提供了必要的类型安全。它还建立在TypeScript强大的类型系统和类型推理之上,不需要代码生成或到处使用手动类型。
Pothos模式构建成一个普通的模式,使用来自graphql 包的类型。这意味着它应该与大多数流行的Node.js的GraphQL服务器实现兼容。在本指南中,我们将使用@graphql-yoga/node 来运行我们的例子,但你可以使用你想要的任何服务器。
用Pothos构建模式
在Pothos中,你通常从数据的形状开始(定义为类型、接口、类、Prisma模型等),然后定义一个使用该数据的GraphQL类型,但不一定符合其形状。Pothos采取的方法在大型应用中感觉更自然,在那里你有真正的数据,而不是纯粹为你的GraphQL API创建的。
除了它的第一手类型安全的优势--它独立于装饰器--Pothos为自己提供了很多以插件形式暴露的功能而感到自豪,这些插件构成了一个庞大的生态系统。Pothos的主要优势之一是将GraphQL API和数据在模式中的内部表示方式分开,我们将在接下来看到这一点。
让我们从Pothos文档中的一个例子开始:从一个 "Hello, World!"应用程序中建立一个简单的模式。
import { createServer } from '@graphql-yoga/node';
import SchemaBuilder from '@pothos/core';
const builder = new SchemaBuilder({});
builder.queryType({
fields: (t) => ({
hello: t.string({
args: {
name: t.arg.string(),
},
resolve: (parent, { name }) => `hello, ${name || 'World'}`,
}),
}),
});
const server = createServer({
schema: builder.toSchema({}),
});
server.start();
在这个例子中,我们用graphl-yoga/node 和Pothos schema builder创建了一个简单的模板服务器。我们从Pothos核心中导入模式构建器,并实例化一个新的模式构建器,它构建了一个GraphQL语言能够理解的普通模式。
之后,我们用我们的字段类型和参数以类型安全的方式设置查询生成器。在对传递给查询的字段参数和查询本身进行了所有必要的验证之后,解析器负责在查询执行时返回一个响应。
最后,我们将构建的模式传递给createServer 函数,并调用server.start 方法。
通过Pothos,我们可以以对象类型的形式定义我们的数据结构,这让我们知道底层数据类型的细节。之后,我们就可以继续定义类型,在这里,我们把我们定义的结构作为验证实际类型的一种方式来传递。
所以,基本上,我们需要一种传递底层数据结构的类型信息的方式,以便我们的字段知道对象类型上有哪些属性。
在类型推断的帮助下,我们可以确认当我们在对象类型上传递错误的字段时,并确保objectType 符合我们的类型定义,因为对象可以告诉我们期待什么类型。基于模式中定义的字段,我们就可以确定可用数据的性质和它们的类型。这意味着,任何我们曾经打算加入我们的模式的数据都必须被明确地定义。
如何在Pothos中定义对象
在Pothos中,有三种定义对象的方法:使用类、模式类型和引用。
定义Pothos类和定义普通的类是一样的--我们结构化我们的数据并初始化该类。请看下面的一个例子。
export class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
在定义了类之后,我们可以为上述类中的字段映射类型。这是用Pothos字段生成器来完成的,以验证我们上述模式类中的对象类型。请看下面我们如何做。
<
pre class="language-graphql hljs>const builder = new SchemaBuilder({})。
builder.objectType(Person, {
name: 'Person Schema',
description: "A person schema",
fields: (t) => ({}),
}) 。
objectParam 参数,Person ,代表我们的初始类,它作为一个蓝图,用于验证我们可以根据该蓝图为每个单独的属性传递的类型。我们这样做是为了当我们在字段中使用这些属性时,我们可以确保它们代表正确的类型。
我们可以在上面的字段对象的帮助下,继续定义我们在上面的模式中的数据种类。让我们看看下面我们是如何做到这一点的。
builder.objectType(Person, {
name: 'Person Schema',
description: 'A person schema',
fields: (t) => ({
nameNew: t.string({
resolve: (parent) => {
const name = console.log(parent.name)
},
}),
ageNew: t.int({
resolve: (parent) => {
const age = console.log(parent.age)
},
}),
}),
});
我们可以看到,我们无法直接访问我们模式中定义的属性。这是设计好的,这样可以确保我们只从底层模式中获得对属性的访问。
注意,父参数将是模式类中指定的当前类型的支持模型的值。
然而,为了获得对模式或模型中定义的字段属性的直接访问,我们可以使用expose ,正如文档中定义的那样。
exposeString(name, options)
注意:name 参数可以是来自支持模型的任何字段,与被暴露的类型相匹配。
接下来,我们实际写一个查询,在解析器的帮助下解析到实际的值,解析器是一个解析这个字段值的函数。下面让我们用Pothos创建这样一个查询。
builder.queryType({
fields: (t) => ({
Person: t.field({
type: Person,
resolve: () => new Person('Alexander', 25),
}),
}),
});
下一步是创建一个简单的服务器,并将我们建立的模式传递给服务器,正如我们前面看到的那样。Pothos与任何流行的GraphQL服务器实现都能很好地工作。
最后,我们针对服务器运行我们的常规GraphQL查询。
query {
Person {
name
age
}
}
Pothos的特点
定义模式的几种方法
正如我们上面所概述的,在用Pothos创建或定义对象类型时(这是一种提供关于你的模式中的底层数据是如何结构的类型信息的方式),我们可以利用上面的类、模式类型,甚至用refs。更多关于如何根据我们的使用情况来使用的信息可以在文档中找到。
打印和生成模式文件
使用Pothos,我们可以用以下方式生成我们的模式文件 graphql-code-generator.你也可以打印你的模式,当你想拥有你的模式的SDL版本时,这很有用。在这种情况下,我们可以使用printSchema 或lexicographicSortSchema ,这两种方法都可以从GraphQL包中导入。
生成类型
Pothos没有一个内置的机制来生成用于客户端的类型,但是graphql-code-generator可以被配置为直接从你的TypeScript文件中消耗一个模式。
Pothos的支持模型
Pothos在你的外部GraphQL API的形状和你的数据的内部表示之间实施了明确的分离。为了帮助实现这种分离,Pothos提供了一个支持模型,让你对如何定义你的模式和解析器使用的类型有很多控制。
Pothos的支持模型在文档中得到了广泛的解释。
基于插件
Pothos 是基于插件的,它提供了像simple-objects,scope-auth, 和mocks 这样的样本插件,使你的工作更容易。例如,simple-objects 插件可以使构建一个图变得更快,因为你不需要为图中的每个对象提供明确的类型或模型。
无主见的
Pothos对代码的结构是没有意见的,它提供了做许多事情的多种方法。事实上,Pothos甚至提供了一个如何组织你的文件的指南。
Pothos SchemaBuilder API
要用Pothos创建一个模式,我们所要做的就是从Pothos核心中导入schemaBuilder ,如下图所示。
import SchemaBuilder from '@pothos/core';
const builder = new SchemaBuilder<{
Context: {};
}>({
// plugins
});
模式创建器有助于为我们的图形创建类型,并将创建的类型嵌入GraphQL模式中。关于Pothos模式构建器API设计的细节可以在文档中找到。
对ORM的支持
虽然Pothos主要是一个模式构建器,但它也支持大多数ORM,特别是通过Pothos的Prisma插件与Prisma集成。有了这个插件,我们可以轻松地定义基于Prisma的对象类型,同样,也可以定义基于Prisma模型的GraphQL类型。文档中显示了一个关于如何去做的例子和设置。
当然,这个集成的一个显著特点是支持强类型的API,自动查询优化(包括关系的n + 1 查询问题),支持基于同一数据库模式的许多不同的GraphQL模型,等等。文档中涵盖了这一切。
注意:Prisma也可以直接与Pothos集成。这个插件只是让我们在使用这两种技术时变得更容易、更有性能、更有效率。关于如何进行这种整合的指南包含了更多的信息。
什么是TypeGraphQL?
TypeGraphQL提供了一种不同的方法来构建模式。通过TypeGraphQL,我们只使用类和装饰器的魔法来定义模式。它主要依赖于 graphql-js, class-validator()以及reflect-metadata shim,它使TypeScript中的反射工作。class-validator 是一个基于装饰器的类的属性验证。
我们在之前的文章中广泛介绍了用TypeGraphQL构建GraphQL APIs,包括如何创建对象类型。
@ObjectType()
class Recipe {
@Field()
title: string;
@Field(type => [Rate])
ratings: Rate[];
@Field({ nullable: true })
averageRating?: number;
}
正如我们在上面看到的,我们通过定义类来开始用TypeGraphQL定义模式,这些类作为我们模式的蓝图。让我们看看下面的一个例子。
首先,我们开始创建与SDL中的类型相似的类型。
type Person {
name: String!
age: Number
dateofBirth: Date
}
接下来,我们可以着手创建类,它必须包含我们的Person 类型的所有属性和定义的类型。
class Recipe {
name: string;
age?: number;
dateofBirth: ate
}
我们利用装饰器来设计类和它的属性,像这样。
@ObjectType()
class Person {
@Field()
name: string;
@Field()
age?: number;
@Field()
dateOfBirth: Date;
}
然后,我们创建我们称之为input 的类型,我们需要这些类型来执行我们的查询和变异。
@InputType()
class NewPersonInput {
@Field()
@MaxLength(40)
name: string;
@Field({ nullable: true })
age?: number;
@Field()
dateOfBirth: Date;
}
字段验证方法,包括maxLength ,都来自于class-validator 库。在创建常规查询和突变之后,最后一步是建立我们将传递给GraphQL服务器的模式。
const schema = await buildSchema({
resolvers: [PersonResolver],
});
下面是我们的Person 类型的一个突变类型的例子。
type Mutation {
addNewPerson (newPersonData: NewPersonInput!): Person!
deletePerson(id: ID!): Boolean!
}
TypeGraphQL的特点
TypeGraphQL功能包括验证、授权等,这有助于开发人员快速编写GraphQL API,并减少为所有参数和输入和/或对象类型创建TypeScript接口的需要。TypeGraphQL还有助于确保每个人通过使用类和一点装饰器的帮助来定义模式,从一个单一的真理来源工作。这确实有助于减少代码的冗余。
支持依赖性注入
TypeGraphQL支持依赖性注入,允许用户提供将被框架使用的IoC容器。
严格的验证
字段属性通过类验证库进行严格验证。TypeGraphQL比Pothos更灵活,在我们可能需要以更灵活的方式声明一些字段的类型的情况下,支持通用类型,如类型参数。
支持自定义装饰器
TypeGraphQL支持自定义装饰器,包括方法和参数,这提供了一个很好的方式来减少模板代码,并在多个解析器中重复使用通用。
对ORM的支持
TypeGraphQL也有对多个不同的第三方ORM的巨大支持,包括TypeORM和Prisma。对于Prisma,TypeGraphQL提供了一个与typegraphql-prisma包的集成,我们可以在npm上找到它。
TypeGraphQL已经有了基于你的Prisma模式生成类型类和解析器的规定,这意味着我们不需要写太多的代码来执行常规查询和突变。文档中有设置这两种技术的例子,也有一个专门的网站,其中包含更多的例子和教程,包括安装说明、配置等内容。
总结
在这篇文章中,我们已经看了两个很棒的、基于TypeScript的库的模式构建方法。虽然Pothos可以用来构建基于TypeScript的GraphQL APIs,但它主要是作为一个模式构建器发光。
另一方面,TypeGraphQL更加灵活,允许我们建立简单的GraphQL API,支持不同的ORM。
我们已经能够在你的Node.js/TypeScript和基于GraphQL的API中涵盖一些重要的功能、用例和模式构建的方法论。这篇文章的目的是向你展示这两个不同的、独特的库是如何处理这些过程的,这样你就可以对未来项目中使用的下一个最佳工具做出明智的决定。
The postPothos vs. TypeGraphQL for TypeScript schema buildingappeared first onLogRocket Blog.