@bsuite/dry-lint

中文文档
1.0.2发布于 2026/08/22UNLICENSEDTypeScriptES Module近 30 天下载 2139

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

中文使用文档
文档目录18 节
  1. bsuite/no-uuid-input-placeholder
  2. 检测模式
  3. 护身符
  4. 允许逃跑
  5. 安装
  6. 使用量
  7. 建议的单行监听
  8. 仅警告(分阶段推出期间有用)
  9. 手动带选项的接线
  10. 应用检测方法
  11. 如何写入检测
  12. 在所有者地图上添加新表格
  13. 单一所有者条目(最常见的)
  14. 多写器条目(PHASE-3c,v0.2.0+)
  15. 版本
  16. 所有者密钥
  17. 已知的违反行为和执法态势
  18. 发展

@bsuite/干-lint (英语)

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

插件运送四项规则:

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

所有权地图位于 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输入.

检测模式

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

护身符

// ✅ 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 用于真-无名称-实体表面(开发者唯一的调试工具)。 以评论记录原因.

安装

pnpm add -D @bsuite/dry-lint

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


使用量

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

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

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

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

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

手动带选项的接线

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 nameApp 密钥
business-suite-unifiedbsu
crm7-complete, (中文(简体) ), crm7crm7
conduitconduit
braden-appbraden
r80-calculator, (中文(简体) ), r80.3r80
throughputthroughput
任意 @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/[email protected]+. 设置两者都是一个计划错误.

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

  1. 打开 src/ownership-map.json。 。 。 .

  2. 添加条目 tables数字 :

    {
      "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操作:

{
  "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风险管理7crm7/
conduit管道(招募苯丙胺类兴奋剂)conduit/
bradenbraden.com.au 公司网站braden/
r80R80.3 工资计算器R80.3/
throughput吞吐量(理想管理)throughput/
shared由多应用程序共同拥有(审计-拖车/仅附件)无
all事件槽——任何应用程序都可以写入无

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

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

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

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

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

发展

# 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 共发布 10 个版本,首次发布于 2026/04/25;过去 12 个月发布了 10 个版本。

版本发布日期距今
1.0.2latest2026/08/222 个月前
1.0.12026/07/243 个月前
1.0.02026/07/233 个月前
0.6.02026/07/203 个月前
0.5.02026/06/035 个月前
0.4.02026/05/066 个月前

关于 @bsuite/dry-lint 的常见问题

@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 和提交记录判断。