# @bsuite/dry-lint 中文文档

规范地址：https://npmcn.com/package/%40bsuite/dry-lint/

版本：1\.0\.2
npm 元数据更新时间：2026-08-22T05:40:38.969Z
中文译文更新时间：2026-11-08T20:45:10.277Z
软件包许可：UNLICENSED

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

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

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

- 包体积（解压后）：143 kB，32 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：eslint \>=9\.0\.0
- 首次发布：2026-04-25T10:25:13.556Z
- 最新版本发布：2026-08-22T05:40:38.788Z
- 近 30 天下载量：2139（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 10 个）

## 中文简介

ESLint插件执行 BSuite 一发架构(单一拥有者Supabase实体表)和OAuth回调桥合同.

## 安装

```sh
npm install @bsuite/dry-lint
```

也可以使用：`pnpm add @bsuite/dry-lint`、`yarn add @bsuite/dry-lint`、`bun add @bsuite/dry-lint`

## README

# @bsuite/干-lint (英语)

执行 BSuite 的 ESLint 平面配置插件 **一发式建筑** ——每个Supabase实体表都有一个单一的犬类所有者应用,而其他应用可能会读取EAD,但从来没有WRITE加入.

插件运送四项规则:

| 规则 | 默认 | 目的 |
| --- | --- | --- |
| `bsuite/no-cross-app-write` | `error` | 应用程序调用时出错 `.from('<table>').{insert,update,upsert,delete}()` 以不同应用程序拥有的表格为对象,使用所有制地图. |
| `bsuite/no-raw-entity-select` | `warn` | 原始旗帜 `.select()` 与条形实体表相读取——鼓励通过打入的实体服务层. |
| `bsuite/no-uuid-input-placeholder` | `error` | 旗帜 `<Input placeholder="UUID of …">` 和类似的 UUID 即时占位符 `<Input>`编号 :`<input>`编号 :`<Textarea>`编号 :`<textarea>`。操作员必须从犬类实体选择器中选择,而不是用手粘贴UUID. |
| `bsuite/oauth-callback-must-bridge` | `error` | 文件调用时出错 `exchangeCodeForTokens()` 没有相应的 `supabase.auth.setSession()` bridge——防止BSU-app交接让用户匿名. |

所有权地图位于 [`src/ownership-map.json`](https://npmcn.com/package/%40bsuite/dry-lint/src/ownership-map.json) 并且来源于 `docs/20260227-dry-one-shot-architecture-v1.04A.md §1` 加上V5-V10的研究结果 `docs/20260423-cross-app-write-audit-v1.00W.md`。 。 。 .

## `bsuite/no-uuid-input-placeholder`

强制操作者使用条形实体选择器而不是自由文本 UUID 输入. 在2026-06-01扫荡后被触发(PRs #933–#939),它取代了16个CRM7页的原始UUID输入.

### 检测模式

```tsx
// ❌ flagged — operator should pick, not paste
<Input placeholder="UUID of host employer" />
<Input placeholder="Enter apprentice UUID" />
<Input placeholder="Apprentice UUID" />
```

### 护身符

```tsx
// ✅ pick from a canonical entity selector
import { EmployerSelector } from '@/components/entity/selectors';

<EmployerSelector
  value={hostEmployerId}
  onSelect={(entity) => setHostEmployerId(entity?.id ?? '')}
/>
```

如果没有选择器,请创建一个镜像 `IncidentSelector` I4图案(租户范围通过明确 `.eq('tenant_id', …)` 在RLS顶部.

### 允许逃跑

-   测试、规格、故事和 `__mocks__` 路径自动跳过.
-   内入 `// eslint-disable-next-line bsuite/no-uuid-input-placeholder` 用于真-无名称-实体表面(开发者唯一的调试工具)。 以评论记录原因.

* * *

## 安装

```bash
pnpm add -D @bsuite/dry-lint
```

该插件为ESLint v9平面配置相容. 它宣布 `eslint >=9` 作为同伴的依赖.

* * *

## 使用量

### 建议的单行监听

```ts
// eslint.config.ts
import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  bsuiteDryLint.configs.recommended, // bsuite/no-cross-app-write: error
  // ...rest of your config
];
```

### 仅警告(分阶段推出期间有用)

```ts
import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  bsuiteDryLint.configs.warn, // bsuite/no-cross-app-write: warn
];
```

### 手动带选项的接线

```ts
import bsuiteDryLint from '@bsuite/dry-lint';

export default [
  {
    plugins: { bsuite: bsuiteDryLint },
    rules: {
      'bsuite/no-cross-app-write': [
        'error',
        {
          // Override the auto-detected app (default: inferred from file path)
          appOverride: 'crm7',
          // Also report writes to tables not in the ownership map (default: false)
          warnOnUnknownTable: true,
        },
      ],
    },
  },
];
```

* * *

## 应用检测方法

规则需要知道一个文件属于哪个应用程序,这样它就可以与所有者地图进行比较. **每个真正的应用配置都通过一个明确的 `appOverride`** (参见以上"图解"示例——每个app的 `eslint.config.js` 套装 `{ appOverride: '<app>' }`因此,在实践中 `appOverride` 是在生产中实际决定应用程序的;下面的自动探测器只在 `appOverride` 省略.

侦测( E)`detectAppFromPath()`, (中文(简体) ), `src/app-detection.ts`从被子上走 **文件自己的目录** 寻找最近的 `package.json`,在第一个 `.git` 标记(文件或目录——覆盖 git-worktree 校对,在哪里) `.git` 是文件指向真正的gitdir。 这个 `package.json` `name` 字段与 :

| `package.json` `name` | App 密钥 |
| --- | --- |
| `business-suite-unified` | `bsu` |
| `crm7-complete`, (中文(简体) ), `crm7` | `crm7` |
| `conduit` | `conduit` |
| `braden-app` | `braden` |
| `r80-calculator`, (中文(简体) ), `r80.3` | `r80` |
| `throughput` | `throughput` |
| 任意 `@bsuite/*` 范围软件包 | `shared` |

若无 `package.json` 于 `.git` 边界,或边界 `name` 不符合,该文件中的规则无操作(未关闭——缺失的检测总是安全的;虚假的归属不是).

**bsuite # 1623: (英语)** 这个探测器的早期版本与路径相匹配 SEGMENTS 代替(例如处理任意 `crm7` 目录名称段作为 CRM7 应用程序). 月台标准破了 `git worktree add /home/<user>/Desktop/Dev/<app>-<feature>-worktree` 公约——工作树被检查为 `bsuite/` 与目录名称不字面等同的应用程序名称——并且错误地将此类文件分配给任何已知的应用程序名称偶然出现在路径的任何地方(包括一个贡献者的自家目录). 这个 `package.json`\-基于上面的行走是免疫的,可以完全命名退出目录.

您可以通过 `appOverride` 选项 —— 和每个运出的应用程序配置 .

* * *

## 如何写入检测

规则走 AST 以任何调用表达式,如果被调用者是一个成员访问,结束于其中之一 `insert`, (中文(简体) ), `update`, (中文(简体) ), `upsert`,或 `delete`。然后沿着查询-构建器链走回,直到找到最接近的 `.from('<literal>')` 调用并解决表格名称.

链走柄:

-   直接通话.. `supabase.from('x').insert(...)`
-   链式查询-构建器呼叫 - `supabase.from('x').select('*').eq('id', 1).update(...)`
-   `await`\-接通了电话
-   在打电话之前,先拨打中间电话 `.from()`\- 不相关的查询方法

它没有报告:

-   读取(`.select(...)`(中文(简体) )
-   调用表格名称为非文体表达式(例如变量)的地方。 这是有意的——我们宁可错过几起病例,也不愿错过垃圾邮件假阳性.
-   调用任何已知应用程序外的文件 .

* * *

## 在所有者地图上添加新表格

每个条目都使用 **完全一个** 联 合 国 `owner` (单行体书写表面)或 `writers` (多作者共同拥有, `@bsuite/dry-lint@0.2.0`+. 设置两者都是一个计划错误.

### 单一所有者条目(最常见的)

1.  打开 [`src/ownership-map.json`](https://npmcn.com/package/%40bsuite/dry-lint/src/ownership-map.json)。 。 。 .
    
2.  添加条目 `tables`数字 :
    
    ```jsonc
    {
      "tables": {
        "your_new_table": {
          "owner": "crm7",        // one of: bsu, crm7, conduit, braden, r80, throughput, shared, all
          "readers": ["bsu"],     // apps that may .select() but never write
          "$comment": "Optional context, e.g. audit reference."
        }
      }
    }
    ```
    
3.  使用 `"shared"` 如果该表由2+应用程序共同拥有,且有文件记载的审计拖拉/仅附加模式(例如. `wage_calculation_snapshots`) (中文(简体) ).
    
4.  使用 `"all"` 用于清晰的事件沉入表(例如. `bi_metrics`) (中文(简体) ).
    

### 多写器条目(PHASE-3c,v0.2.0+)

对于由明确允许的应用程序列表共同拥有的管理员-CRUD表格(例如. `tenants` + 键 `user_tenants`,其中BSU是平台所有人和CRM7的租户-管理边缘功能在RLS下执行合法的Org-admin操作:

```jsonc
{
  "tables": {
    "your_co_owned_table": {
      "writers": ["bsu", "crm7"],   // explicit allow-list — at least one app
      "readers": ["r80", "conduit"], // apps that may .select() only
      "$comment": "Why this is multi-writer rather than single-owner."
    }
  }
}
```

该规则会通过任何上市的应用程序的书写和旗下非上市的应用程序的书写 `crossAppWriteMultiWriter` 留言.

### 版本

弹出 `@bsuite/dry-lint` 版本(patch for new tables, small for owners moves 或 schema 添加)并重用.

* * *

## 所有者密钥

| 密钥 | 应用 | 还原 |
| --- | --- | --- |
| `bsu` | 商业统一 | `business-suite-unified/` |
| `crm7` | 风险管理7 | `crm7/` |
| `conduit` | 管道(招募苯丙胺类兴奋剂) | `conduit/` |
| `braden` | braden.com.au 公司网站 | `braden/` |
| `r80` | R80.3 工资计算器 | `R80.3/` |
| `throughput` | 吞吐量(理想管理) | `throughput/` |
| `shared` | 由多应用程序共同拥有(审计-拖车/仅附件) | 无 |
| `all` | 事件槽——任何应用程序都可以写入 | 无 |

* * *

## 已知的违反行为和执法态势

消费者应用软件应该有线 `bsuite/no-cross-app-write` 作为 `error`. 先前存在 遗留的写入路径必须用狭义的每个文件覆盖来隔离 消费者ESLint配置;在警告-模式中不要保留基础规则.

2026-04-27 第2D阶段晋级移动了BSU,CRM7,Conduit,R80.3,Braden,和 在保留有文件记载的例外的同时对错误级执行的流量 用于第五阶段所有权迁移工作.

在所有者映射编辑后运行干运行的帮助以识别任何例外列表 可删除的:

```bash
pnpm --filter @bsuite/dry-lint build
node packages/dry-lint/scripts/dry-run.mjs
```

* * *

## 发展

```bash
# Install (use --ignore-workspace until package is added to pnpm-workspace.yaml)
cd packages/dry-lint && pnpm install --ignore-workspace

# Build
pnpm build

# Run tests
pnpm test
```

## 常见问题

### @bsuite/dry-lint 是什么？

ESLint插件执行 BSuite 一发架构\(单一拥有者Supabase实体表\)和OAuth回调桥合同\.

### 如何安装 @bsuite/dry-lint？

在项目目录运行 npm install @bsuite/dry-lint，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：eslint（\>=9\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @bsuite/dry-lint 支持 TypeScript 吗？

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

### @bsuite/dry-lint 支持 ESM 还是 CommonJS？

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

### @bsuite/dry-lint 可以商用吗？

@bsuite/dry-lint 使用 UNLICENSED 许可。作者声明为 UNLICENSED，即不授予公开使用许可（与公共领域的 Unlicense 不同）。使用前需获得作者授权。以上为概括，不构成法律意见，请以许可原文为准。

### @bsuite/dry-lint 的下载量有多少？

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

### @bsuite/dry-lint 还在维护吗？

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

