Command Palette

Search for a command to run...

Docs
Hooks 和工具函数

Hooks 和工具函数

Pivot 提供的强大 React Hooks 和工具函数库,简化 OpenAPI 数据处理。

Pivot 不仅提供了丰富的组件,还内置了一套强大的 React Hooks工具函数,专门用于处理 OpenAPI 规范数据。这些工具让您能够轻松地解析、处理和操作 OpenAPI 数据结构。

🎣 React Hooks

useOpenApi

最核心的 Hook,提供了处理 OpenAPI 规范的完整功能。

import { useOpenApi } from "@/hooks/use-openapi";
import type { OpenAPIV3 } from "openapi-types";
 
function ApiComponent({ spec }: { spec: OpenAPIV3.Document }) {
  const openApi = useOpenApi(spec);
 
  // 获取按标签分组的操作
  const operationsByTag = openApi.getOperationsByTag();
 
  // 解析引用
  const resolved = openApi.resolve(someReference);
 
  // 获取模式类型
  const type = openApi.getSchemaType(schema);
 
  // 处理参数
  const processedParams = openApi.processParameters(parameters);
 
  return (
    <div>
      {Object.entries(operationsByTag).map(([tag, operations]) => (
        <div key={tag}>
          <h3>{tag}</h3>
          {operations.map((op) => (
            <div key={op.path + op.method}>
              {op.method} {op.path}
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}

主要功能

  • 操作处理getOperationsByTag()getOperation(path, method)
  • 模式处理getSchemaType()getSchemaProperties()getSchemaConstraints()
  • 引用解析resolve()
  • 参数处理processParameters()getRequestBodySchema()
  • 响应处理processResponse()
  • 基本信息getInfo()getServers()getTags()getComponents()

useOpenApiLoader

智能的 OpenAPI 数据加载器,支持多种数据源。

import { useOpenApiLoader } from "@/hooks/use-openapi-loader";
 
function ApiComponent() {
  // 从 URL 加载
  const { spec, loading, error } = useOpenApiLoader({
    type: "url",
    data: "https://api.example.com/openapi.json",
  });
 
  // 从字符串加载
  const { spec: specFromString } = useOpenApiLoader({
    type: "string",
    data: yamlString,
  });
 
  // 从对象加载
  const { spec: specFromObject } = useOpenApiLoader({
    type: "object",
    data: openapiObject,
  });
 
  if (loading) return <div>加载中...</div>;
  if (error) return <div>加载失败: {error}</div>;
  if (!spec) return <div>无数据</div>;
 
  return <ApiExplorer spec={spec} />;
}

功能特性

  • 多数据源支持:URL、字符串、对象
  • 自动格式检测:JSON 和 YAML
  • 错误处理:网络错误、解析错误
  • 加载状态:loading、error 状态管理
  • 缓存机制:避免重复加载

useOpenApiCombined

结合了加载和解析功能的综合 Hook。

import { useOpenApiCombined } from "@/hooks/use-openapi-combined";
 
function ApiDocumentation({ url }) {
  const {
    spec,
    loading,
    error,
    openApi, // 已初始化的 useOpenApi 实例
    operations,
    tags,
  } = useOpenApiCombined({ type: "url", data: url });
 
  if (loading) return <div>加载 API 规范中...</div>;
  if (error) return <div>错误: {error}</div>;
 
  return (
    <div>
      <h1>{spec.info.title}</h1>
      {Object.entries(operations).map(([tag, ops]) => (
        <div key={tag}>
          <h2>{tag}</h2>
          {ops.map((op) => (
            <OperationCard key={`${op.path}-${op.method}`} {...op} />
          ))}
        </div>
      ))}
    </div>
  );
}

特性优势

  • 一体化解决方案:加载 + 解析合二为一
  • 预处理数据:operations、tags 数据已预处理
  • 性能优化:内置缓存和防抖处理
  • 类型安全:完整的 TypeScript 支持

useOperation

专门处理单个 API 操作的 Hook。

import { useOperation } from "@/hooks/use-operation";
 
function OperationComponent({ operation, path, method }) {
  const op = useOperation(operation, path, method);
 
  const operationId = op.getOperationId();
  const tags = op.getTags();
  const parameters = op.getParameters();
  const requestBody = op.getRequestBody();
  const responses = op.getResponses();
  const security = op.getSecurity();
 
  return (
    <div>
      <h3>{operationId}</h3>
      <div>Tags: {tags.join(", ")}</div>
      <div>Parameters: {parameters.length}</div>
      <div>Has Request Body: {!!requestBody}</div>
      <div>Response Count: {Object.keys(responses).length}</div>
    </div>
  );
}

主要方法

  • 基本信息getOperationId()getSummary()getDescription()
  • 分类标签getTags()
  • 参数处理getParameters()getParametersByIn()
  • 请求体getRequestBody()getRequestBodySchema()
  • 响应处理getResponses()getSuccessResponses()
  • 安全设置getSecurity()isSecured()
  • 外部文档getExternalDocs()

useSchema

处理 OpenAPI Schema 对象的专用 Hook。

import { useSchema } from "@/hooks/use-schema";
 
function SchemaComponent({ schema, components }) {
  const schemaData = useSchema(schema, components);
 
  const type = schemaData.getType();
  const properties = schemaData.getProperties();
  const required = schemaData.getRequired();
 
  const isNameRequired = schemaData.isRequired("name");
  const isEmailRequired = schemaData.isRequired("email");
 
  return (
    <div>
      <div>Type: {type}</div>
      <div>Required Fields: {required.join(", ")}</div>
      <div>Properties:</div>
      {Object.entries(properties).map(([key, prop]) => (
        <div key={key} className="ml-4">
          {key}: {schemaData.isRequired(key) ? "Required" : "Optional"}
        </div>
      ))}
    </div>
  );
}

主要功能

  • 类型处理getType()isObject()isArray()
  • 属性处理getProperties()getProperty(name)
  • 必填检查getRequired()isRequired(name)
  • 约束处理getConstraints()getEnum()
  • 示例数据getExample()getExamples()
  • 描述信息getDescription()getTitle()

🛠️ 工具函数

resolveRef

解析 OpenAPI 中的 $ref 引用。

import { resolveRef } from "@/lib/resolve-ref";
import type { OpenAPIV3 } from "openapi-types";
 
// 解析 Schema 引用
const resolvedSchema = resolveRef<OpenAPIV3.SchemaObject>(
  { $ref: "#/components/schemas/User" },
  components
);
 
// 解析参数引用
const resolvedParam = resolveRef<OpenAPIV3.ParameterObject>(
  { $ref: "#/components/parameters/PageSize" },
  components
);
 
// 解析响应引用
const resolvedResponse = resolveRef<OpenAPIV3.ResponseObject>(
  { $ref: "#/components/responses/NotFound" },
  components
);
 
// 处理深层嵌套引用
const nestedRef = { $ref: "#/components/schemas/NestedUser" };
const resolved = resolveRef(nestedRef, components);

特性

  • 自动解析嵌套引用:支持引用的引用
  • 类型安全:完整的 TypeScript 类型支持
  • 错误处理:优雅处理无效引用
  • 智能缓存:避免重复解析相同引用

generateExample

根据 OpenAPI Schema 自动生成示例数据。

import { generateExample } from "@/lib/generate-example";
 
// 基本用法
const example = generateExample(schema, components);
 
// 高级配置
const example = generateExample(schema, components, {
  maxDepth: 3, // 最大递归深度
  includeReadOnly: false, // 是否包含只读属性
  includeWriteOnly: true, // 是否包含只写属性
  useExamples: true, // 优先使用 schema 中的示例
  locale: "zh", // 生成本地化示例
});

支持的数据类型

  • 基础类型:string、number、integer、boolean
  • 复杂类型:object、array
  • 复合模式:allOf、oneOf、anyOf
  • 格式化字符串:date、date-time、email、uuid、url 等
  • 约束条件:enum、pattern、min/max 等

智能生成

根据属性名自动生成合适的示例:

// 自动识别常见字段
{
  "name": "张三",           // 识别姓名字段
  "email": "user@example.com", // 识别邮箱字段
  "phone": "+86-138-0013-8000",   // 识别电话字段
  "address": "北京市朝阳区", // 识别地址字段
  "company": "某某科技有限公司",   // 识别公司字段
  "website": "https://example.com", // 识别网站字段
  "birthday": "1990-01-01", // 识别生日字段
  "avatar": "https://avatar.example.com/user.jpg" // 识别头像字段
}

schema-utils

Schema 处理的辅助工具函数。

import {
  isReferenceObject,
  isSchemaObject,
  getSchemaType,
  mergeSchemas,
  flattenAllOf,
  extractEnumValues,
  getSchemaConstraints,
} from "@/lib/schema-utils";
 
// 类型检查
if (isReferenceObject(obj)) {
  console.log("这是一个引用对象");
}
 
if (isSchemaObject(obj)) {
  console.log("这是一个 Schema 对象");
}
 
// 获取类型
const type = getSchemaType(schema); // "object", "array", "allOf" 等
 
// 处理复合 Schema
const merged = mergeSchemas([schema1, schema2]);
const flattened = flattenAllOf(allOfSchema);
 
// 提取枚举值
const enumValues = extractEnumValues(enumSchema);
 
// 获取约束条件
const constraints = getSchemaConstraints(schema);

主要功能

  • 类型检查isReferenceObjectisSchemaObject
  • 类型提取getSchemaTypegetSchemaFormat
  • Schema 合并mergeSchemasflattenAllOf
  • 约束处理getSchemaConstraintsextractEnumValues
  • 递归处理walkSchematransformSchema

type-utils

类型处理的工具函数。

import {
  getSchemaType,
  isPrimitiveType,
  isComplexType,
  normalizeType,
  getTypeHierarchy,
  formatTypeDisplay,
} from "@/lib/type-utils";
 
// 类型判断
const type = getSchemaType(schema);
const isPrimitive = isPrimitiveType(type);
const isComplex = isComplexType(type);
 
// 类型规范化
const normalized = normalizeType(rawType);
 
// 获取类型层次
const hierarchy = getTypeHierarchy(schema);
 
// 格式化类型显示
const displayType = formatTypeDisplay(type, format);

核心功能

  • 类型判断isPrimitiveTypeisComplexTypeisNumericType
  • 类型转换normalizeTypeformatTypeDisplay
  • 类型分析getTypeHierarchygetCompatibleTypes
  • 验证工具validateTypeisValidFormat

🌍 国际化系统

useI18n Hook

完整的国际化支持,内置中英文翻译。

import { useI18n } from "@/lib/i18n";
 
function MyComponent() {
  const { t, locale, setLocale, availableLocales } = useI18n();
 
  return (
    <div>
      <h1>{t("api.title")}</h1>
      <p>{t("operation.parameters")}</p>
      <p>{t("schema.required")}</p>
 
      <div className="space-x-2">
        {availableLocales.map((loc) => (
          <button
            key={loc}
            onClick={() => setLocale(loc)}
            className={locale === loc ? "font-bold" : ""}
          >
            {loc === "zh" ? "中文" : "English"}
          </button>
        ))}
      </div>
 
      <div>Current locale: {locale}</div>
    </div>
  );
}

API 说明

  • t(key, params?):翻译函数,支持参数插值
  • locale:当前语言设置
  • setLocale(locale):切换语言
  • availableLocales:可用语言列表

I18nProvider

国际化上下文提供者,在应用根部使用。

import { I18nProvider } from "@/lib/i18n";
 
function App() {
  return (
    <I18nProvider defaultLocale="zh">
      <YourAppComponents />
    </I18nProvider>
  );
}

翻译键值对

常用操作术语

{
  "operation": {
    "parameters": "参数",
    "requestBody": "请求体",
    "responses": "响应",
    "security": "安全",
    "deprecated": "已废弃",
    "callbacks": "回调",
    "summary": "摘要",
    "description": "描述",
    "operationId": "操作ID",
    "tags": "标签"
  }
}

Schema 相关

{
  "schema": {
    "type": "类型",
    "format": "格式",
    "required": "必填",
    "optional": "可选",
    "properties": "属性",
    "items": "数组项",
    "additionalProperties": "额外属性",
    "example": "示例",
    "examples": "示例",
    "enum": "枚举值",
    "default": "默认值",
    "pattern": "正则模式",
    "constraints": "约束条件"
  }
}

HTTP 相关

{
  "http": {
    "method": "方法",
    "path": "路径",
    "status": "状态码",
    "headers": "请求头",
    "query": "查询参数",
    "body": "请求体",
    "form": "表单数据",
    "file": "文件"
  }
}

操作按钮

{
  "action": {
    "copy": "复制",
    "expand": "展开",
    "collapse": "收起",
    "tryItOut": "在线测试",
    "generate": "生成",
    "download": "下载",
    "share": "分享",
    "edit": "编辑"
  }
}

扩展翻译

您可以通过修改 registry/default/lib/i18n/locales/ 目录下的文件来扩展翻译:

// 添加新语言支持
// registry/default/lib/i18n/locales/es.ts
export const es = {
  operation: {
    parameters: "Parámetros",
    requestBody: "Cuerpo de Solicitud",
    // ... 更多翻译
  },
};

📦 批量安装

安装所有 Hooks

安装工具库

单独安装

# 安装单个 Hook
npx shadcn@latest add https://pivotkit.vercel.app/r/use-openapi.json
npx shadcn@latest add https://pivotkit.vercel.app/r/use-openapi-loader.json
 
# 安装单个工具函数
npx shadcn@latest add https://pivotkit.vercel.app/r/resolve-ref.json
npx shadcn@latest add https://pivotkit.vercel.app/r/generate-example.json

💡 使用建议

1. 组合使用 Hooks

// 推荐的组合使用模式
function ApiExplorer({ url }) {
  // 使用组合 Hook 一次性获取所有数据
  const { spec, openApi, operations, loading, error } = useOpenApiCombined({
    type: "url",
    data: url,
  });
 
  // 对特定操作使用专用 Hook
  const currentOp = useOperation(selectedOperation, path, method);
 
  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorMessage error={error} />;
 
  return <ApiInterface spec={spec} operations={operations} />;
}

2. 错误处理

// 完善的错误处理
function ApiComponent() {
  const { spec, loading, error } = useOpenApiLoader({
    type: "url",
    data: apiUrl,
  });
 
  if (loading) return <div>正在加载 API 规范...</div>;
 
  if (error) {
    return (
      <div className="error">
        <h3>加载失败</h3>
        <p>{error}</p>
        <button onClick={() => window.location.reload()}>重试</button>
      </div>
    );
  }
 
  return <ApiDocumentation spec={spec} />;
}

3. 性能优化

// 使用 React.memo 优化渲染
const OperationCard = React.memo(({ operation, path, method }) => {
  const op = useOperation(operation, path, method);
  // ... 渲染逻辑
});
 
// 使用 useMemo 缓存计算结果
function ParametersList({ parameters, components }) {
  const processedParams = useMemo(
    () =>
      parameters.map((param) => ({
        ...param,
        resolved: resolveRef(param, components),
      })),
    [parameters, components]
  );
 
  return <ParameterList items={processedParams} />;
}

通过这些强大的 Hooks 和工具函数,您可以轻松构建复杂的 OpenAPI 文档界面,同时保持代码的简洁和可维护性。