okfetch

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

okfetch

okfetch

Use this skill when the user wants to build HTTP clients or requests with the okfetch library.
当用户想要使用okfetch库构建HTTP客户端或请求时,可使用本技能。

Package selection

包选择指南

Choose the package based on the job:
  • Use
    @okfetch/fetch
    for direct typed requests with validation, retries, plugins, auth, timeouts, and streaming.
  • Use
    @okfetch/api
    when the user wants a typed client generated from endpoint definitions.
  • Use
    @okfetch/logger
    when the user wants ready-made request logging through a plugin.
If the user has repeated endpoint calls, shared request shapes, or wants one typed client object, prefer
@okfetch/api
.
If the user just needs a few requests or wants fine-grained transport control, prefer
@okfetch/fetch
.
根据需求选择对应的包:
  • 若需要直接发送带类型校验、重试、插件、认证、超时和流处理的请求,请使用
    @okfetch/fetch
  • 若用户希望根据端点定义生成带类型的客户端,请使用
    @okfetch/api
  • 若用户需要通过插件实现现成的请求日志功能,请使用
    @okfetch/logger
如果用户需要重复调用端点、共享请求结构,或想要一个统一的带类型客户端对象,优先选择
@okfetch/api
如果用户只需要发送少量请求,或希望对传输层进行细粒度控制,优先选择
@okfetch/fetch

Core mental model

核心设计理念

okfetch stays close to the web platform. It makes
fetch
safer and more composable without hiding how HTTP requests work.
The main usage pattern is:
  1. Define Zod schemas for request or response shapes.
  2. Call
    okfetch(...)
    directly or generate a client with
    createApi(...)
    .
  3. Handle the returned
    Result
    explicitly instead of relying on thrown request errors.
okfetch贴近Web平台设计,它让
fetch
更安全、更具组合性,同时不会掩盖HTTP请求的工作原理。
主要使用模式如下:
  1. 为请求或响应结构定义Zod Schema。
  2. 直接调用
    okfetch(...)
    ,或使用
    createApi(...)
    生成客户端。
  3. 显式处理返回的
    Result
    对象,而非依赖抛出的请求错误。

Result handling

Result处理

Request calls return a
Result
, not thrown transport or validation errors for expected failures.
Prefer examples and implementations that use:
  • .match(...)
  • .isOk()
    /
    .isErr()
  • other
    better-result
    helpers already available to the user
Do not default to
try/catch
for normal HTTP failure handling.
请求调用会返回
Result
对象,对于预期的失败场景,不会抛出传输或校验错误。
推荐使用以下方式处理:
  • .match(...)
  • .isOk()
    /
    .isErr()
  • 用户已有的其他
    better-result
    工具函数
不要默认使用
try/catch
处理常规HTTP失败场景。

@okfetch/fetch

@okfetch/fetch

Use
okfetch(url, options)
for direct requests.
Common options:
  • outputSchema
    to validate successful responses
  • apiErrorDataSchema
    to validate structured error payloads
  • params
    and
    query
    to build request URLs
  • body
    for JSON request payloads
  • auth
    for basic, bearer, or custom authorization headers
  • retry
    for
    fixed
    ,
    linear
    , or
    exponential
    retries
  • timeout
    for request timeouts
  • plugins
    for lifecycle extensions
  • stream: true
    for SSE-style streaming
Prefer this shape in examples:
ts
import { okfetch } from "@okfetch/fetch";
import { z } from "zod/v4";

const userSchema = z.object({
  id: z.number(),
  name: z.string(),
});

const result = await okfetch("https://api.example.com/users/1", {
  outputSchema: userSchema,
});

result.match({
  err: (error) => {
    console.error(error._tag, error.message);
  },
  ok: (user) => {
    console.log(user.name);
  },
});
When showing error validation, use
validateClientErrors
or
validateAllErrors
from
@okfetch/fetch
.
Error tags to mention when relevant:
  • FetchError
  • TimeoutError
  • ApiError
  • ParseError
  • ValidationError
  • PluginError
Validation boundaries to keep straight:
  • outputSchema
    validates successful responses
  • apiErrorDataSchema
    validates structured error bodies
  • validateClientErrors
    applies validation to
    4xx
    responses
  • validateAllErrors
    applies validation to
    4xx
    and
    5xx
    responses
使用
okfetch(url, options)
发送直接请求。
常用配置项:
  • outputSchema
    :校验成功响应的结构
  • apiErrorDataSchema
    :校验结构化错误载荷
  • params
    query
    :构建请求URL
  • body
    :JSON请求体
  • auth
    :基础认证、Bearer认证或自定义认证头
  • retry
    :固定间隔、线性或指数退避重试
  • timeout
    :请求超时时间
  • plugins
    :生命周期扩展插件
  • stream: true
    :启用SSE风格的流处理
示例推荐使用如下结构:
ts
import { okfetch } from "@okfetch/fetch";
import { z } from "zod/v4";

const userSchema = z.object({
  id: z.number(),
  name: z.string(),
});

const result = await okfetch("https://api.example.com/users/1", {
  outputSchema: userSchema,
});

result.match({
  err: (error) => {
    console.error(error._tag, error.message);
  },
  ok: (user) => {
    console.log(user.name);
  },
});
展示错误校验时,请使用
@okfetch/fetch
中的
validateClientErrors
validateAllErrors
相关场景下可提及以下错误标签:
  • FetchError
  • TimeoutError
  • ApiError
  • ParseError
  • ValidationError
  • PluginError
需明确以下校验边界:
  • outputSchema
    校验成功响应
  • apiErrorDataSchema
    校验结构化错误体
  • validateClientErrors
    4xx
    响应应用校验
  • validateAllErrors
    4xx
    5xx
    响应应用校验

@okfetch/api

@okfetch/api

Use
createEndpoints(...)
plus
createApi(...)
when the user wants a typed client from endpoint definitions.
Endpoint definitions may include:
  • method
  • path
  • body
  • params
  • query
  • output
  • error
  • requestOptions
  • stream
This package validates
body
,
params
, and
query
before sending the request, then delegates transport behavior to
@okfetch/fetch
.
Prefer this shape in examples:
ts
import { createApi, createEndpoints } from "@okfetch/api";
import { z } from "zod/v4";

const todoSchema = z.object({
  id: z.number(),
  title: z.string(),
  completed: z.boolean(),
});

const endpoints = createEndpoints({
  todos: {
    get: {
      method: "GET",
      output: todoSchema,
      params: z.object({ id: z.number() }),
      path: "/todos/:id",
    },
  },
});

const api = createApi({
  baseURL: "https://api.example.com",
  endpoints,
});

const result = await api.todos.get({ params: { id: 1 } });
Use
ApiService
when the user wants a class wrapper around a generated client.
ts
import { ApiService, createEndpoints } from "@okfetch/api";
import { z } from "zod/v4";

const todoSchema = z.object({
  id: z.number(),
  title: z.string(),
  completed: z.boolean(),
});

const endpoints = createEndpoints({
  todos: {
    getById: {
      method: "GET",
      output: todoSchema,
      params: z.object({ id: z.number() }),
      path: "/todos/:id",
    },
  },
});

class TodoService extends ApiService(endpoints) {
  constructor() {
    super({
      baseURL: "https://api.example.com",
    });
  }

  getById(id: number) {
    return this.client.todos.getById({
      params: { id },
    });
  }
}

const todoService = new TodoService();
const result = await todoService.getById(1);
Important behavior:
  • global
    createApi(...)
    options act as shared transport defaults
  • per-endpoint
    requestOptions
    refine behavior for one endpoint
  • per-call overrides win over endpoint-level and global defaults
  • response parsing, retries, auth, plugins, timeouts, and streaming still come from
    @okfetch/fetch
当用户希望根据端点定义生成带类型的客户端时,使用
createEndpoints(...)
搭配
createApi(...)
端点定义可包含以下内容:
  • method
  • path
  • body
  • params
  • query
  • output
  • error
  • requestOptions
  • stream
该包会在发送请求前校验
body
params
query
,然后将传输行为委托给
@okfetch/fetch
示例推荐使用如下结构:
ts
import { createApi, createEndpoints } from "@okfetch/api";
import { z } from "zod/v4";

const todoSchema = z.object({
  id: z.number(),
  title: z.string(),
  completed: z.boolean(),
});

const endpoints = createEndpoints({
  todos: {
    get: {
      method: "GET",
      output: todoSchema,
      params: z.object({ id: z.number() }),
      path: "/todos/:id",
    },
  },
});

const api = createApi({
  baseURL: "https://api.example.com",
  endpoints,
});

const result = await api.todos.get({ params: { id: 1 } });
当用户需要为生成的客户端添加类包装时,使用
ApiService
ts
import { ApiService, createEndpoints } from "@okfetch/api";
import { z } from "zod/v4";

const todoSchema = z.object({
  id: z.number(),
  title: z.string(),
  completed: z.boolean(),
});

const endpoints = createEndpoints({
  todos: {
    getById: {
      method: "GET",
      output: todoSchema,
      params: z.object({ id: z.number() }),
      path: "/todos/:id",
    },
  },
});

class TodoService extends ApiService(endpoints) {
  constructor() {
    super({
      baseURL: "https://api.example.com",
    });
  }

  getById(id: number) {
    return this.client.todos.getById({
      params: { id },
    });
  }
}

const todoService = new TodoService();
const result = await todoService.getById(1);
重要行为说明:
  • 全局
    createApi(...)
    配置项作为共享的传输层默认设置
  • 单个端点的
    requestOptions
    可覆盖该端点的默认行为
  • 单次调用的配置优先级高于端点级和全局默认配置
  • 响应解析、重试、认证、插件、超时和流处理仍由
    @okfetch/fetch
    提供支持

@okfetch/logger

@okfetch/logger

Use
logger()
from
@okfetch/logger
as a plugin for request lifecycle logging.
Prefer this shape in examples:
ts
import { okfetch } from "@okfetch/fetch";
import { logger } from "@okfetch/logger";

await okfetch("https://api.example.com/health", {
  plugins: [logger()],
});
When useful, mention
logDataOnSuccess
as the main option for including parsed success payloads in logs.
The logger plugin covers these lifecycle moments:
  • request start
  • success
  • failure
  • retry
使用
@okfetch/logger
中的
logger()
作为插件,实现请求生命周期日志记录。
示例推荐使用如下结构:
ts
import { okfetch } from "@okfetch/fetch";
import { logger } from "@okfetch/logger";

await okfetch("https://api.example.com/health", {
  plugins: [logger()],
});
必要时可提及
logDataOnSuccess
配置项,它是在日志中包含解析后的成功响应数据的主要选项。
日志插件覆盖以下生命周期节点:
  • 请求开始
  • 请求成功
  • 请求失败
  • 请求重试

Streaming

流处理

When the user asks about streaming or server-sent events:
  • use
    stream: true
  • explain that each SSE
    data:
    chunk is parsed independently
  • if
    outputSchema
    is present, explain that each chunk is validated before emission
当用户询问流处理或服务器发送事件(SSE)相关内容时:
  • 启用
    stream: true
    配置
  • 说明每个SSE的
    data:
    块会被独立解析
  • 如果配置了
    outputSchema
    ,说明每个块在输出前都会被校验

Guidance for answers

回答指导

  • Keep examples TypeScript-first.
  • Use
    zod/v4
    in examples.
  • Prefer consumer-facing code snippets over repository implementation details.
  • Keep the distinction between transport concerns and endpoint-definition concerns clear.
  • If a user asks which package to use, answer with a recommendation, not a neutral dump of all APIs.
  • 示例优先使用TypeScript编写。
  • 示例中使用
    zod/v4
  • 优先展示面向开发者的代码片段,而非仓库实现细节。
  • 明确区分传输层相关关注点和端点定义相关关注点。
  • 如果用户询问应使用哪个包,请给出明确推荐,而非中立地罗列所有API。