GraphQL Mobius
GraphQL 到 TypeScript 类型转换,无需代码生成,使用类似 Prisma 的查询语法,完全类型安全。
纯粹用 TypeScript 类型编写。
由 ElysiaJS 为您呈现
Mobius 可以将 GraphQL schema 解析为 TypeScript,以创建端到端类型安全的 GraphQL 客户端。
这是通过模板字面量和各种黑魔法实现的。
已知限制:
- 注释中不能包含 "{}" (大括号),否则类型将无法解析
- 不支持嵌套片段
- TypeScript 的总堆栈有限,传递约 8-9 行代码 / 14k 生成约 900 个类型 (压缩后,仅类型)
为什么
这证明了可以在端到端类型安全的情况下运行 GraphQL。
这是一个最小实用工具库,不打算替代像 URQL 和 GraphQL Apollo 这样的 GraphQL 客户端。
Mobius 作为一个配套库或内部引擎,为新的或现有的库添加类型安全层。
Mobius 做两件事:
- 将 GraphQL 推断为 TypeScript 类型
- 一个使用类似 Prisma 语法查询 GraphQL 的最小客户端
您可以在您的库/框架中使用 Mobius,只需在 LICENSE 中提及您正在使用 GraphQL Mobius(它是 MIT 许可证,可以随意分叉或改进)
前提条件
- TypeScript > 5.0
- 在 tsconfig.json 中将
strict
设置为 true
开始使用
- 在字符串中定义 GraphQL Schema (必须是 const)
- 使用
typeof
将 schema 转换为类型(或在构造函数中将其作为字面量参数传递)
import { Mobius } from 'graphql-mobius'
const typeDefs = `
type A {
A: String!
B: String!
}
type Query {
Hello(word: String!): A!
}
`
const mobius = new Mobius<typeof typeDefs>({
// 使用 Mobius 默认的 fetch 客户端
url: 'https://api.saltyaom.com/graphql'
})
// 如果您不关心 TypeDefs 在客户端是否可用,这样也可以
const mobius2 = new Mobius({
url: 'https://api.saltyaom.com/graphql'
typeDefs
})
// 调用 query 执行查询
const result = await mobius.query({
Hello: {
where: {
word: 'Hi'
},
select: {
A: true
}
}
})
result
.then(x => x?.Hello.A)
.then(console.log)
Mobius 客户端
Mobius 客户端提供以下方法:
- $:一次查询所有类型的查询
- query:查询 GraphQL
- mutate:变更 GraphQL
- subscription:订阅 GraphQL
Mobius 客户端提供以下属性:
- mobius:仅用于类型声明
- fragments:类型安全的 GraphQL 片段(类型始终提供,如果传递了
typeDefs
,则提供字面代码)
Mobius 类型
Mobius 类型扩展了 Record<string, unknown>
,基础如下:
- Query:
Record<string, unknown>
- Mutation:
Record<string, unknown>
- Subscription:
Record<string, unknown>
- Fragment:
Record<string, unknown>
- 其余类型声明从 GraphQL Schema 推断
标量
您可以通过传递类型作为第二个泛型来添加自定义标量类型。
import { Mobius } from 'graphql-mobius'
const typeDefs = `
type A {
A: String!
B: Date!
}
`
type Scalars = {
Data: Date
}
const client = new Mobius<typeof typeDefs>()
client.klein
/**
* A: {
* A: string
* B: Date
* }
*/
如果未提供标量但在 GraphQL 中定义了,它应该解析为 unknown
解析器
您可以使用 Mobius 为 GraphQL Apollo 和 GraphQL Yoga 严格类型化 Resolvers
函数。
使用 Mobius 实例
import { Mobius } from 'graphql-mobius'
const typeDefs = `
type A {
A: String!
B: String!
}
type Query {
Hello(word: String!): A!
}
`
const mobius = new Mobius({
typeDefs
})
const resolvers = {
Query: {
Hello(_, { word }) {
return {
A: "Hello",
B: "Hello"
}
}
}
} satisfies typeof mobius.resolvers
使用类型定义
import type { CreateMobius, Resolvers } from 'graphql-mobius'
const typeDefs = `
type A {
A: String!
B: String!
}
type Query {
Hello(word: String!): A!
}
`
type Resolver = Resolvers<CreateMobius<typeof typeDefs>>
const resolvers = {
Query: {
Hello(_, { word }) {
return {
A: "Hello",
B: "Hello"
}
}
}
} satisfies Resolver
片段
如果您提供了 typeDefs 作为字面代码,您可以使用 mobius.fragment
片段语法类似于剩余参数,看起来像 GraphQL 片段语法。
const typeDefs = `
interface A {
A: String!
B: String!
C: String!
D: String!
}
fragment APart on A {
A
B
}
type Query {
GetA: A!
}
`
const mobius = new Mobius({
typeDefs
})
const { APart } = mobius.fragments!
mobius.query({
GetA: {
...APart,
C: true
}
})
实用类型
对于框架和库作者。
您可以使用从 graphql-mobius 导出的实用类型来实现端到端的类型安全,同时完全不增加项目包的大小。
import type { CreateMobius } from 'graphql-mobius'
const typeDefs = `
# Hello World
type A {
A: String!
B: String!
}
# Hello World
type Query {
Hello(word: String!): A!
}
`
// 这相当于调用 new Mobius().klein
type Engine = CreateMobius<typeof typeDefs>
结构
CreateMobius
将返回类型结构,扩展 Record<string, unknown>
,基础如下:
- Query:
Record<string, unknown>
- Mutation:
Record<string, unknown>
- Subscription:
Record<string, unknown>
- Fragment:
Record<string, unknown>
- 其余类型声明从 GraphQL Schema 推断
其他实用工具
CreateMobius (Type)
- 将 GraphQL 类型推断为 TypeScriptResolver (Type)
- 将 GraphQL 类型推断为 TypeScriptRemoveComment (Type)
- 在类型级别移除 GraphQL 注释CreateQuery (Type)
- 为客户端创建类似 Prisma 的参数语法MakeExecutable (Type)
- 为 GraphQL 创建类似 Prisma 的函数mobiusToGraphQL
- 将类似 Prisma 的 JSON 映射到 GraphQL 查询(字符串)createFragment
- 为类似 Prisma 的客户端创建片段
关于 fetch
如前所述,Mobius 并不打算替代现有的 GraphQL 客户端,而是设计用于创建一个抽象层。
允许您通过提供具有以下类型的自定义 fetcher 与现有库集成:
type Fetcher = (query: string) => Promise<unknown>
Fetch 函数是在新请求调用时执行的回调函数,它接受一个字符串化的 GraphQL 查询,并期望返回一个 GraphQL 响应。
它的用法如下:
// 使用 URQL
new Mobius({
fetch: urql.query
})
// 使用原生 fetch(默认)
new Mobius({
fetch: (query) => fetch(this.config.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
variables: {}
}),
})
.then((res) => res.json())
})
您想用来查询 GraphQL 以与 Mobius 一起使用的库由您选择,它就是这样设计的。
GraphQL Mobius 是一个将 GraphQL 转换为 TypeScript 类型的库,无需代码生成,纯粹使用 TypeScript 类型。
它并不打算替代现有的 GraphQL 客户端,而是创建一个抽象层。
您可以在您的源代码/库/框架中自由使用 Mobius,只需保留原始的 LICENSE(MIT 许可证)
由 ElysiaJS 为您呈现