@alxia/graphql

中文文档
0.14.0发布于 2026/11/04MITTypeScriptES Module零依赖近 30 天下载 3231

带有 GraphQL Yoga 的 alxia 图形QL : 其插件, 订阅 SSE 或 WebSocket (graphql-ws) 和 GraphiQL , 在 app 的钩子后, 解析器读取 app 的上下文

中文使用文档
文档目录14 节
  1. 使用量
  2. 二. 背景情况
  3. 夹克 (N+1)
  4. 每个请求一个值
  5. 瑜伽的插件
  6. 运行的操作
  7. 网络安全套
  8. 订户
  9. 限制
  10. 错误、健康和关闭
  11. 正在进行
  12. 测试
  13. API 密码
  14. 文档

@alxia/graphql (英语)

图QL,用于 阿尔克夏,服务于 图QL 瑜伽。终点是 与其它路线一样: 在应用程序的中间器件后方, 由它的守卫,它的 解析器读取所建的中间软件的上下文 —— 键入并检查. 瑜伽的插件系统是你的: Envelop的插件和瑜伽自己的.

bun add @alxia/graphql graphql-yoga graphql @alxia/core
bun add -d typescript

graphql-yoga 财务报告和审定财务报表 graphql 是对等方: 软件包宣布不依赖. graphql-ws 是一个可选的,因为 ws 一个人. graphql 16和17都工作; 与17, graphql-yoga 必须是5.22或 后来,第一个接受. graphql-yoga 5(从5.16起)和6个工作; 6号线的规格 瑜伽6号 @graphql-hive/logger Logger 作为习惯 logging 价值,及其 @graphql-yoga/plugin-* 4.x需要瑜伽6号.

瑜伽本身的要求 ID 是关闭(requestId: false: 客户同意 x-request-id 从来没有回音或记录, 所以应用程序自己的ID是唯一的。 通过 requestId: true 或对象保存 trustHeader: false 除非你设定它. 瑜伽5号被忽略了 requestId。 。 。 . logging 默认为 'warn' 两个主,所以 瑜伽6的每条请求的INFO线路关闭 和从未设置的应用程序 logging 没有 更长的时间可以看到瑜伽的信息行;通过 logging: true 或者说 'info' 为了得到他们.

使用量

import { alxia } from '@alxia/core';
import { graphql, type GraphQLContext } from '@alxia/graphql';
import { bearer } from '@alxia/jwt';
import { createSchema } from 'graphql-yoga';

const base = alxia()
    .decorate({ db })
    .use(bearer({ jwt, schema: Claims }));        // every route after it needs a token

const schema = createSchema<GraphQLContext<typeof base>>({
    typeDefs: /* GraphQL */ `type Query { me: String! }`,
    resolvers: {
        Query: { me: (_, __, { user, db }) => db.name(user.sub) }, // user and db typed
    },
});

const app = base.plugin((app) => graphql(app, { schema }));   // POST and GET /graphql
app.listen(3000);

graphql(app, options) 添加 GET 财务报告和审定财务报表 POST 路线 path —— 说 /graphql 默认情况下,在应用的前缀下——并返回应用. 鉴于 改为 app.plugin 作为函数,它停留在链中,并看到应用程序的类型.

二. 背景情况

解脱者上下文为瑜伽request, (中文(简体) ), params),应用程序的每个 decorate,每个 derive每一个中间器件的: user, (中文(简体) ), db, (中文(简体) ), log, (中文(简体) ), requestId - 和 set,通过它设置一个标题或饼干:

login: async (_, { name }, { set }) => {
    set.cookies.set('session', await sign(name), { httpOnly: true });
    return true;
},

GraphQLContext<typeof app> 是那种类型。 解脱者读出 应用程序未构建的是一个编译错误 :

the schema's resolvers read a context the app does not build: missing user

夹克 (N+1)

一个每个家长都装入记录的字段—— Note.author 超过50个音符,即 51个查询。 构建 数据记录器 内 页:1 context 选项并输入 GraphQLContext第二届 参数。 (约加的) batching 选项,下面是另一回事: 操作在一个 HTTP 请求中 。 )

bun add dataloader
import DataLoader from 'dataloader';

const createLoaders = () => ({
    user: new DataLoader(async (ids: readonly string[]) => findUsers(ids)), // one query for all ids
});
type Loaders = ReturnType<typeof createLoaders>;

const schema = createSchema<GraphQLContext<typeof base, { loaders: Loaders }>>({
    typeDefs,
    resolvers: { Note: { author: (note: { authorId: string }, _, { loaders }) => loaders.user.load(note.authorId) } },
});

const app = base.plugin((app) => graphql(app, { schema, context: () => ({ loaders: createLoaders() }) }));

每个请求, 从未为进程做过一次: 数据记录器缓存它的内容 装入,所以一个共享的 将服务 steal records 并交出一个用户的数据 到下一个。 在韦伯索克特, context 运行每个操作。 见 用 DataLoader 连接。 。 。 .

每个请求一个值

解决许多父母相同价值的字段(类别: 20件)应装入一次. oncePerRequest(context, key, load) 运行 load 第一次请求 key 返回该值 对同一请求的每个后来的呼叫。 缓存随 上下文对象,和 a load 投出或拒绝的,是不被保存的.

import DataLoader from 'dataloader';
import { oncePerRequest } from '@alxia/graphql';

const categories = (context: object) =>
    oncePerRequest(context, 'categories', () => new DataLoader(loadCategories)); // one DataLoader per request and key

const category = (item: { categoryId: string }, _args: unknown, context: object) =>
    categories(context).load(item.categoryId);

变异会一个接一个地运行它的根子, 一个会改变什么 后一读出. 以 freshPerMutation 所以每个根 变异字段从空缓存开始( 它的子字段共享); 查询 保留一个缓存 :

import { freshPerMutation } from '@alxia/graphql';

const resolvers = freshPerMutation({ Query, Mutation, Ward });

无需依赖: dataloader 留在你身边。 见 每个请求一个值。 。 。 .

瑜伽的插件

每个瑜伽选择都通过,但是 graphqlEndpoint,哪个 path 套装和 graphiql,哪个 ide 决定:

import { useDepthLimit } from '@envelop/depth-limit';
import { useResponseCache } from '@graphql-yoga/plugin-response-cache';

graphql(app, {
    schema,
    plugins: [useDepthLimit({ maxDepth: 8 }), useResponseCache({ session: ({ request }) => ... })],
    maskedErrors: true,            // Yoga's default: an error's message never leaks
    ide: Bun.env.NODE_ENV === 'development' && 'apollo-sandbox', // at runtime, never process.env: bun build inlines it
    batching: true,
});
  • 订阅 服务于服务器发送事件, 瑜伽默认值 : async *subscribe 在一个决心中, Accept: text/event-stream 编辑 请求; 也在 WebSocket 上 ws: true。 。 。 . @alxia/compress 默认情况下只留下一个事件流.

  • 一个IDE 回复 a GET 从端点的浏览器中取出,带有 Content-Security-Policy 它可以装入 unpkg 上的被绑起的文件 仅此而已,没有受到任何人的指责 @alxia/secure-headers 继续 以 默认, 服务应用程序中的 GraphiQL 单独 dev(NODE_ENV=development, (中文(简体) ), 或者说 alxia({ dev: true })),无; ide 在任何地方选择一个:

    graphql(app, { schema }); // GraphiQL in dev, nothing deployed
    graphql(app, { schema, ide: 'apollo-sandbox', sandbox: { initialDocument: '{ me }' } });
    
    ide
    无( 默认)瑜伽的GraphiQL in dev (英语:isDev),没有其他
    'graphiql'瑜伽的GraphiQL,到处都是; graphiql 选择
    'apollo-sandbox'阿波罗沙盒,嵌入,指向页面打开的地址,前缀包括—— https 在终止 TLS 的代理服务器后面( )IDE 指南) (中文(简体) ). sandbox 带 title, (中文(简体) ), initialDocument, (中文(简体) ), initialHeaders, (中文(简体) ), pollForSchemaUpdates, (中文(简体) ), includeCookies
    false无
  • (简体中文) 实值 @alxia/cors整个应用程序的,瑜伽本身的关闭,除非 cors 给出.

运行的操作

每个电话都是 POST /graphql· ; graphql() 告诉周围的观察者 执行的操作。 后面,我们走 use(logger()) 请求的行 携带 operationName 财务报告和审定财务报表 operationType后边 use(telemetry({ … })) 其跨度被命名为 query GetNotes,与 打开遥测 graphql.operation.name 财务报告和审定财务报表 graphql.operation.typeA级 分批体是一行一横, batch和每个名字.

const app = alxia()
    .use(logger())
    .use(telemetry({ service: 'notes' }))
    .plugin((app) => graphql(app, { schema }));

请求 在未执行姓名之前被拒绝。 完毕 ws: true,每个操作 套接字是一条线和一条长度,从它的 subscribe 消息 以错误回答时标出. 见 终点指南 财务报告和审定财务报表 网页标签指南。 。 。 .

网络安全套

ws: true 服务于 WebSocket 上的终点 graphql-transport-ws 议定书 graphql-ws, (中文(简体) ), 阿波罗客户端的默认值 GraphQLWsLink 还有urql的 subscriptionExchange。 。 。 . graphql-ws 是一个可选的对等点; 服务器发送 事件始终如一。 安装它 bun add graphql-ws。 。 。 .

const app = base.plugin((app) => graphql(app, { schema, ws: true })); // ws://…/graphql too
import { createClient } from 'graphql-ws';

const client = createClient({ url: 'wss://api.example.com/graphql', connectionParams: { device: 'web' } });

升级后运行了应用程序的中间软件——一名警卫 401 拒绝 套接字,他们添加的是上下文,除了 connectionParams 发送的客户端——每次操作都经过 瑜伽的插件,然后关闭套接字 1001,并填写 他们的订阅. ws: { path, keepAlive } 移动套接字或空格 它的 p. 见 网页标签指南, (中文(简体) ), 阿波罗客户端和urql的设置包含在内.

订户

import { boundedStream } from '@alxia/graphql';

// Your pub/sub reader and your session check.
declare function subscribeToTopic(topicId: string): AsyncIterable<unknown>;

const subscribe = (
    _: unknown,
    args: { topicId: string },
    ctx: { assertSession(): Promise<void> },
) =>
    boundedStream(subscribeToTopic(args.topicId), {
        idleMs: 90_000,
        totalMs: 10 * 60_000,
        checkEveryMs: 30_000,
        check: () => ctx.assertSession(),
    });

当闲去或老去时 溪流会清净地结束 check 抛出,和 客户端离开后立即释放源. 见 瑜伽的插件和选项。 。 。 .

限制

4个限制 约束一个请求的成本 在任何解析器运行之前。 文档 最多可持有 15,000个纪念品 (单位:千美元)maxTokens, (中文(简体) ), false 无上限: 更长 一个被解析器拒绝为 GRAPHQL_PARSE_FAILED,400下 application/graphql-response+json永远也达不到计划 也许 最多一个巢 1 000级 联 合 国 {, (中文(简体) ), ( 财务报告和审定财务报表 [ (单位:千美元)maxNesting, (中文(简体) ), false 页:1 无限制 : 图ql- js 通过重现来解析并溢出数个堆栈 1000个水平下降,所以更深层的文件 被拒绝的方式相同 之前 帕塞尔再现,从来就不是500。 这算数 {, (中文(简体) ), ( 财务报告和审定财务报表 [ 一起来, 参数和所包括的列表,因此这不是一项深入选择的规则 验证规则 这个 将瑜伽解析器保存在以重量为界的缓存中, 64个小米B 百分比 终点, 1 024 (英语) 文档, 一小时 (单位:千美元)parseCache),即瑜伽的自有之处 没有大小绑定。 A 类 POST 尸体可以持有 1个小米B (单位:千美元)bodyLimit除非 app 声明自己的 bodyLimit() 在此之前 graphql(),保存; 尸体 过去是核心的413 而且从来没有到达瑜伽. bodyLimit 范围 a POST 单独: 一个 WebSocket subscribe 信件以 Bun 为界 maxPayloadLength (默认为16 MiB) :

graphql(app, {
    schema,
    maxTokens: 20_000, // false: no cap
    maxNesting: 2_000, // 1 000 by default; false: no cap
    parseCache: { maxBytes: 32 * 1024 * 1024, max: 512, ttl: 30 * 60_000 }, // false: no cache
    bodyLimit: 5 * 1024 * 1024, // 1 MiB by default; a multipart upload needs more
});

拒绝的文件是200 errors 下级 application/json (400名以下) application/graphql-response+json) (中文(简体) ). 一个错误的选项值丢出一个 TypeError 地点 graphql() 已经宣布.

客户端查询为上千个符;入门查询为163个. 见 要求的代价。 。 。 .

错误、健康和关闭

GraphQL 错误将保留 GraphQL —— 条目 errors[]在200块之内.. 时 @alxia/core是因为 alxia({ errors: 'problem' }) 使 HTTP 层 rFC 9457问题:一个警卫的401,一个413,a 五百来. health() 旁边挂起,然后继续 SIGTERM 飞行中的询问 在进程退出前, 订阅结束 :

import { alxia, health } from '@alxia/core';
import { graphql } from '@alxia/graphql';

const app = alxia({ errors: 'problem' })
    .plugin(health())
    .plugin((app) => graphql(app, { schema }));
app.listen({ port: 4000 });

见 终点指南。 。 。 .

正在进行

graphqlExecutor(options) 运行此过程中的查询或突变,其中 相同的插件、限制、解析缓存和错误掩码为 graphql(),则a 您通过服务器上下文:用于 MCP 工具或任务,而不是浏览器.

import { graphqlExecutor } from '@alxia/graphql';

const execute = graphqlExecutor({ schema, plugins: [useAuth()] });
const { data, errors } = await execute({ query: '{ me { id } }' }, { viewer });

见 指南。 。 。 .

测试

graphqlClient 从 @alxia/graphql/testing 向应用程序发送操作 进行中,通过 app.fetch: 无端口. 这是一个子路径,所以主条目 生产包从不携带.

import { graphqlClient } from '@alxia/graphql/testing';

const client = graphqlClient(app, { headers: { authorization: `Bearer ${token}` } });
const { status, data, errors } = await client.query(
    'query ($name: String!) { hello(name: $name) }',
    { variables: { name: 'Ada' } },
);

A 类 TypedDocumentNode 类型 data 和变量. method: 'GET' 发送 uRL中的操作; persisted 使一尘不染地, 当应用程序不允许其他任何内容时( 您命名 ) TData);客户端添加了否 证监会头条,把你的 headers数字 :

const result = await client.query<{ hello: string }>({ persisted: hash, method: 'GET' });

见 测试指南。 。 。 .

API 密码

导出
graphql(app, options)终点 : schema, (中文(简体) ), path, (中文(简体) ), ide, (中文(简体) ), sandbox, (中文(简体) ), ws, (中文(简体) ), maxTokens, (中文(简体) ), maxNesting, (中文(简体) ), parseCache, (中文(简体) ), bodyLimit,每个瑜伽选择
graphqlExecutor(options)(request: { query, operationName?, variables? }, context, { signal? }?) => Promise<{ data?, errors? }>: 正在通过下列选项进行查询或突变: graphql() (没有路线)path, (中文(简体) ), ide, (中文(简体) ), ws, (中文(简体) ), bodyLimit, (中文(简体) ), cors(中文(简体) )
ExecutorRequest, (中文(简体) ), ExecutorResult, (中文(简体) ), ExecutorError, (中文(简体) ), ExecutorCall, (中文(简体) ), GraphQLExecutor, (中文(简体) ), GraphQLExecutorOptions类型
GraphQLWsOptionsws选项 : path, (中文(简体) ), keepAlive
GraphQLWsContext在WebSocket上的操作增加了上下文的内容: connectionParams
renderSandbox(endpoint, options?), (中文(简体) ), SANDBOX_POLICYsandbox 页面和它装入的策略
SandboxOptions其选项: title, (中文(简体) ), initialDocument, (中文(简体) ), initialHeaders, (中文(简体) ), pollForSchemaUpdates, (中文(简体) ), includeCookies
GraphQLContext<App, UserContext?>解脱者读出
oncePerRequest(request, key, load)load()'值,每个请求对象最多一次计算 key 联合国 string; 返回 T一言为定, 一言不发
clearRequestCache(request)虚空什么 oncePerRequest 为请求对象保留; 下一次调用负载; 返回 void
freshPerMutation(resolvers)与下列函数相同的解析器(相同的类型) Mutation 包起来打电话 clearRequestCache(context) 首先:每个根突变字段开始为空,它的子字段共享,一个查询未受影响
boundedStream(source, options)source (单位:千美元) AsyncIterable 或者说 AsyncIterator作为 AsyncIterableIterator<T> 订阅费 subscribe: 结束于 idleMs 没有事件 totalMs 总之,运行 check 每个 checkEveryMs ,在最后一个检查是 checkDebounceMs 老了,扔东西 mapError(error) 何时 check 失败或源本身抛出,并调用源的 return() 连接或任何端口
BoundedStreamOptions其选项: idleMs, (中文(简体) ), totalMs, (中文(简体) ), checkEveryMs, (中文(简体) ), checkDebounceMs?, (中文(简体) ), check, (中文(简体) ), mapError?, (中文(简体) ), signal?
ServerContext<Ctx>, (中文(简体) ), GraphQLOptions类型
graphqlClient(app, { path?, headers?, method? }) (单位:千美元)@alxia/graphql/testing(中文(简体) )query(document, { variables?, operationName?, headers?, method?, extensions?, persisted? }),或 query({ persisted }) 没有文档,正在处理中: { status, data?, errors?, response }
GraphQLClient, (中文(简体) ), GraphQLResult, (中文(简体) ), QueryDocument, (中文(简体) ), QueryOptions, (中文(简体) ), PersistedQueryOptions, (中文(简体) ), HttpMethod, (中文(简体) ), GraphQLClientOptions, (中文(简体) ), ResponseError (单位:千美元)@alxia/graphql/testing(中文(简体) )类型

文档

版本与发布记录

@alxia/graphql 共发布 32 个版本,首次发布于 2026/10/04;过去 12 个月发布了 32 个版本。

版本发布日期距今
0.14.0latest2026/11/043 天前
0.13.32026/11/025 天前
0.13.22026/11/016 天前
0.13.12026/10/317 天前
0.13.02026/10/317 天前
0.12.02026/10/299 天前

关于 @alxia/graphql 的常见问题

@alxia/graphql 是什么?

带有 GraphQL Yoga 的 alxia 图形QL : 其插件, 订阅 SSE 或 WebSocket (graphql-ws) 和 GraphiQL , 在 app 的钩子后, 解析器读取 app 的上下文

如何安装 @alxia/graphql?

在项目目录运行 npm install @alxia/graphql,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:graphql(^16.11.0 || ^17.0.0)、typescript(^6.0.3 || ^7.0.0)、@alxia/core(^0.19.0)、graphql-yoga(^5.16.0 || ^6.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@alxia/graphql 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alxia/graphql 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@alxia/graphql 可以商用吗?

@alxia/graphql 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@alxia/graphql 的下载量有多少?

根据 npm 官方下载统计,@alxia/graphql 在 2026/10/06 – 2026/11/04 这 30 天内被下载 3,231 次,日均约 108 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alxia/graphql 还在维护吗?

最新版本 0.14.0 发布于 2026/11/04(3 天前);至今共发布 32 个版本,其中过去 12 个月发布了 32 个;首次发布于 2026/10/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。