Files
pnoker 843ee444ca docs: translate design and selection documents to Chinese
Translate the seven remaining English documents under docs/ in place,
preserving all technical content, code blocks, identifiers, links, and
decision IDs (D1-D19, F1-F15, P0-P5). Add a categorized Chinese
navigation index (docs/README.md) with per-document summaries, the
storage supersession chain, and task-based reading paths.
2026-08-28 02:07:45 +08:00

4.7 KiB
Raw Permalink Blame History

dc3-sdk:框架无关的客户端 SDK(设计)

状态:提案(phase 0 已落地) · 范围:web / cli / 未来 app · 驱动因素:A1(设备无关语义)、 docs/design/frontend-three-terminal-ux.md 中的边界纪律

问题

HTTP 网关契约目前被实现了两次:

  • dc3-web/src/api/30 个模块)——薄 axios 封装,与 @/config/axiosElement Plus 通知、路由守卫 401 流程)及 Vite @/ 别名耦合。
  • dc3-cli/src/core/client.ts——为认证(token/salt、token/generate、token/cancel)手写的 fetch 调用。

原生 appReact Native)则需要第三套实现。每个新端点、请求头与错误码解释都必须逐客户端重复实现—— 这是对 A1 的持续性违反。

目标

一个 TypeScript SDK,将网关契约精确实现一次,供 web、CLI 与未来的 app 客户端共同消费。该 SDK 框架无关: 无 Vue、无 Element Plus、无 vue-i18n、不硬依赖 axios。

包结构

dc3-sdk/
├── src/
│   ├── core/            http adapter contract, envelope R<T>, pagination,
│   │                    token/session lifecycle, error taxonomy
│   ├── api/             one module per domain (driver/device/point/...),
│   │                    mirroring backend CRUD verbs (getXxx/listXxx/add/update/delete)
│   ├── types/           PageQuery/PageResult, Record types, domain enums
│   ├── i18n/            (optional) locale dictionaries as plain JSON
│   └── index.ts
├── tests/               vitest with an in-memory mock adapter
└── package.json

核心契约

// HTTP transport abstraction — web injects axios, RN/node injects fetch.
interface HttpClient {
  request<T>(config: {
    method: 'get' | 'post' | 'put' | 'delete';
    url: string;
    params?: Record<string, unknown>;
    data?: unknown;
    headers?: Record<string, string>;
  }): Promise<R<T>>;
}

// Interceptors owned by the HOST, not the SDK: auth headers and 401
// handling stay in the consuming app (web keeps its axios interceptors).
interface SdkOptions {
  http: HttpClient;
  baseUrl: string;
  apiPrefix?: string; // default '/api/v3'
  onUnauthorized?: () => void; // host-provided redirect/logout policy
}

认证/会话:SDK 暴露 salt/generate/cancel/change-password 以及 TokenStore 抽象(webhttpOnly cookie——空实现;CLI:内存/文件;app:经宿主适配器访问 Keychain)。存储策略 永远不由 SDK 决定。

语义层(L1)可移植性

实体 schema 在本次迭代中已经去框架化:

  • EntityListConfig 及相关类型以翻译后的字符串承载标签,字符串由 Translator = (key, params?) => string 生成——Vue 的 ComposerTranslation 在结构上满足该签名;16 个配置模块 不再 import vue-i18n。
  • 下一步:把 EntityListConfig 类型移入 SDK 的 types 层,使 web 与 app 渲染同一份 schema (配置仍留在宿主应用中,共享的是形状)。

未来选项:通过 OpenAPI 导出(make openapi)由后端下发 JSON schema,在不改动客户端的前提下取代手写配置。

边界规则(可用 lint 强制)

在 dc3-sdk 内部,禁止 import 以下内容:

  • vue / vue-router / pinia / element-plus / vue-i18n
  • @/config/* 宿主基础设施
  • 任何仅浏览器才有的全局对象,除非位于 typeof window 守卫之后

在 SDK 包配置中用 eslint no-restricted-imports / import/no-extraneous-dependencies 规则强制执行。

迁移计划

  1. Phase 0(已落地)L1 配置去框架化——引入 Translator 类型,16 个实体配置模块零 vue-i18n import。
  2. Phase 1:搭建 dc3-sdk 包(pnpm workspace),移植 PageQuery/PageResultR<T> 信封、错误分类体系;使用 mock 适配器的 vitest。
  3. Phase 2:移植 30 个 API 封装模块;针对后端 OpenAPI 规范(或录制的 fixture)做契约测试。
  4. Phase 3dc3-web 接入 SDK——删除 src/api,保留 axios 适配器 + 拦截器作为宿主粘合层;删除任何内容之前 先跑完整 e2e(608 个单元测试 + Playwright)。
  5. Phase 4dc3-cli 用 SDK 替换其手写的 fetch 认证(移除重复的 salt/generate/cancel 流程)。
  6. Phase 5app 客户端通过 fetch/Keychain 适配器消费 SDK。

验证

  • SDK 单元测试在 node 中运行,零 DOM/Vue importCI 断言: SDK 源码中不存在 import ... from 'vue')。
  • Web 回归门禁:pnpm check + lint + 完整 vitest + Playwright e2e。
  • CLI 门禁:dc3-cli 的 vitest 套件针对 mock 适配器保持通过。

修订记录

2026-08v1——提案,Phase 0 已落地(Translator 去框架化,16 个模块)。