# @dsh-workbench/shared 中文文档

规范地址：https://npmcn.com/package/%40dsh-workbench/shared/

版本：1\.2\.12
npm 元数据更新时间：2026-11-13T09:14:38.720Z
中文译文更新时间：2026-11-13T03:37:19.823Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40dsh-workbench/shared
原文对照：https://npmcn.com/package/%40dsh-workbench/shared/?lang=original
项目主页：https://github.com/novaeth/dsh-workbench#readme
源码仓库：https://github.com/novaeth/dsh-workbench

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：2.7 MB，780 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：6 个
- peer 依赖：react \*
- 首次发布：2026-10-02T12:21:21.483Z
- 最新版本发布：2026-11-13T09:14:38.472Z
- 近 30 天下载量：17037（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：105（近 12 个月 105 个）

## 中文简介

工作台与模块共享的纯代码与契约类型：类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进（不影响浏览器产物）。

## 安装

```sh
npm install @dsh-workbench/shared
```

也可以使用：`pnpm add @dsh-workbench/shared`、`yarn add @dsh-workbench/shared`、`bun add @dsh-workbench/shared`

## README

# @dsh-workbench/shared

工作台与模块共用的**契约与纯代码**：类型、纯函数、哑组件、i18n、宿主侧工具。 它不持有状态、不依赖外壳运行时、不产生全局副作用 —— 所以外壳和每个模块都可以各自打一份， 不会打架。

对模块作者来说，这里是「不用自己重画」的那一层：卡片壳、行、表单、链接、加载态都在 `components/`，契约类型都在 `contract/`。**dsh 有的原语走 kit，工作台自己的视觉用这里的组件**， 两者拼出面板，不要从 DOM + CSS 重写一遍。

## 四个导出面

| 入口 | 谁用 | 有什么 |
| --- | --- | --- |
| `@dsh-workbench/shared` | 浏览器侧 | 契约类型、纯函数、哑组件（样式随组件）、i18n、读通道 `apiGet` / `factOfRoute` |
| `@dsh-workbench/shared/host` | 宿主侧（Node） | 数据根、git、http、面板状态、单元声明、请求配方 composer 等，**有 `node:*`** |
| `@dsh-workbench/shared/testing` | 测试 | 宿主侧假件、从 `package.json` 读模块声明 |
| `@dsh-workbench/shared/contract/*` | 插件 / 适配器（仅类型） | 契约子路径；`exports` 里的 `./contract/*`，只给类型用 |

两条硬边界：

-   **根入口是浏览器安全的**：不许出现 `node:*`。宿主侧取运行值只走 `/host`。
-   **模块源码对根入口只许 `import type`**：取运行值会在浏览器里打进第二份实例，也会让 `dist/host.js` 在 Node 里 import 不进来。这条由 module-tools 的 `source` 判据盯着。

组件样式与组件同目录（`X.css` / `X.module.css`），构建时原样搬到 `dist/` —— 消费方不用另配 CSS 处理。

## 收录判据

进这个包的东西要同时满足三条，缺一条就留在外壳里：

1.  **无模块级可变状态**：顶层 `let` / `var`、被写入的顶层 `Map` / `Set` 都不行。共享包会被每个 消费者各打一份，带状态就是各说各话。`scripts/check-state.mjs` 守这一条。
2.  **不依赖外壳运行时**：不 import 外壳的代码、不假设自己在哪一列里渲染。
3.  **不产生全局副作用**：import 即注册、改全局、读环境都不行；要环境就从参数或 `/host` 进。

判断不了就问一句：**这份东西被复制成两份，会有什么坏结果？** 答案不是「没有」就别放进来。

## 目录

| 落点 | 是什么 |
| --- | --- |
| `src/api/` | 浏览器侧接缝：读 / 写通道、平台客户端 |
| `src/contract/` | 契约：单元清单、卡片面、读 / 写通道、长任务、审批、面板状态 |
| `src/components/` | 哑组件：`Card` / `CardHead` / `Rows` / `Form` / `FormRow(s)` / `FormActions` / `Link` / `Stack` / 各态块 |
| `src/config/` | 常量与存储键 |
| `src/i18n/` | zh / en 字典、合并与设置 |
| `src/lib/` | 纯函数：文本、忙碌态、表单问题、看板事实 |
| `src/host/` | 宿主侧内核与领域：http、facts、面板状态、workspace、单元声明、执行缝、文件写（`fs-write`：原子写 / JSON / 权限）、受控 env（`env-policy`：product / unit / bootstrap / promptless） |
| `src/testing/` | 测试假件与声明读取 |

`src/index.ts` 与 `src/host.ts` 是**生成的 barrel**：新增文件后跑 `pnpm run barrels`，别手抄。 它会拦重名导出（`export *` 会静默丢掉其中一个）。

## 怎么用

```ts
// 外壳
import { Card, Rows, type UnitManifest } from '@dsh-workbench/shared';
import { workbenchRoot } from '@dsh-workbench/shared/host';

// 模块
import type { UnitClientFace } from '@dsh-workbench/shared';
import { kit } from '@dsh-workbench/core/client';
```

规矩按调用方分：

-   **外壳自己**从根入口取运行值（组件、`apiGet`…），它是这份代码的主人。
-   **模块**的组件从 kit 取：`import { kit } from '@dsh-workbench/core/client'`，根入口只许 `import type`。宿主侧要运行值走 `/host`，浏览器侧要纯函数走 kit —— 两侧都不该从根入口取， 否则浏览器会打进第二份实例、宿主侧会让 `dist/host.js` 在 Node 里 import 不进来。
-   模块里只取类型时写成单独一行 `import type { … }`，别和运行值混在一条语句里 —— `source` 判据按语句判「是不是只取类型」。

组件是**哑的**：props 进、界面出，不取数、不读宿主、不自己决定什么时候刷新。取数在外壳的 hooks 或模块自己的 `model/` 里，所以同一张卡片在真数据和夹具下长得一样。

## 开发

```bash
pnpm --filter @dsh-workbench/shared run build      # tsc + 打类型 + 搬 CSS
pnpm --filter @dsh-workbench/shared run test
pnpm --filter @dsh-workbench/shared run selfcheck  # check-state：无模块级可变状态
```

两个 barrel 用 `pnpm run barrels` 重生成；`pnpm run arch` 跑这个包自己的分层配置。 代码零注释，只有公开成员的导出 JSDoc 例外（它会进 `.d.ts`，是给消费方看的）。

## 官方 dsh 包只在编译期

官方 `@deepseek-ai/dsh-*` 全部在 `devDependencies`：本仓编译时按包名取真类型， 但装包的人不会再把这棵树带进 profile（ADR-0112）。`dependencies` 只剩 `@deepseek-ai/cordis` / `cordis-plugin-loader` 与 dayjs / execa / semver / write-file-atomic， `react` 仍是 peer。

模块契约（`@dsh-workbench/core/contract`）只交工作台自己的类型：`HostContext` / `ClientContext` / `ToolDefinition` / `ToolRegistry` / `ToolRunContext`，以及 `UnitManifest` 与 kit；它不引用 dsh。官方 `Dsh*` 别名只留给工作台内部（宿主侧在 `/host`，客户端侧在根入口）， 模块不需要它们。如果模块作者自己要直接引某个 `Dsh*` 别名，就把对应的官方包放进**自己的** `devDependencies`，编译期拿真类型，装进 profile 仍然不带 dsh。

`selfcheck` 会拒绝 `dependencies` 里出现 `@deepseek-ai/dsh*` —— 这条一红，装进 profile 的就是 第二份 dsh 插件层。

## 相关文档

| 想了解 | 读 |
| --- | --- |
| 层序、两个运行时、槽位、数据通路 | [ARCHITECTURE.md](https://npmcn.com/package/ARCHITECTURE.md) |
| 组件怎么选、kit 里有什么 | [KIT.md](https://npmcn.com/package/%40dsh-workbench/core/skills/workbench-module-diy/KIT.md) |
| 模块的构建与门禁 | [module-tools](https://npmcn.com/package/%40dsh-workbench/module-tools/README.md) |
| 最小模块样本 | [module-hello](https://npmcn.com/package/%40dsh-workbench/module-hello/README.md) |
| 环境与提交 | [CONTRIBUTING.md](https://npmcn.com/package/CONTRIBUTING.md) |

## 常见问题

### @dsh-workbench/shared 是什么？

工作台与模块共享的纯代码与契约类型：类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进（不影响浏览器产物）。

### 如何安装 @dsh-workbench/shared？

在项目目录运行 npm install @dsh-workbench/shared，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（\*）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @dsh-workbench/shared 支持 TypeScript 吗？

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

### @dsh-workbench/shared 支持 ESM 还是 CommonJS？

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

### @dsh-workbench/shared 可以商用吗？

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

### @dsh-workbench/shared 的下载量有多少？

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

### @dsh-workbench/shared 还在维护吗？

最新版本 1\.2\.12 发布于 2026/11/13（今天）；至今共发布 105 个版本，其中过去 12 个月发布了 105 个；首次发布于 2026/10/02。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

