ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

eslint-plugin-drizzle 0.2.2 解析:修复嵌套对象中 drizzleObjectName 检测问题的技术细节

2026/9/19 13:20:25 拓冰建站 浏览量
eslint-plugin-drizzle 0.2.2 解析:修复嵌套对象中 drizzleObjectName 检测问题的技术细节 eslint-plugin-drizzle 0.2.2 解析修复嵌套对象中 drizzleObjectName 检测问题的技术细节【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm导读本文围绕 eslint-plugin-drizzle 0.2.2 版本的核心修复——「当drizzleObjectName指向嵌套对象时规则检测不再失效」——展开结合仓库源码与测试用例深入剖析enforce-delete-with-where与enforce-update-with-where两条规则的工作机制、drizzleObjectName选项的三种取值形态以及嵌套对象如this.dataSource.db.delete()场景下的成员表达式解析原理。读完本文你将能够准确理解该插件在 0.2.2 版本中解决了什么问题、修复如何落地以及在自己的项目中如何正确配置这两条防止危险 SQL 的规则。一、0.2.2 版本变更一条修复的含义0.2.2 变更日志 只记录了一条变更fix: Correct detection ofdrizzleObjectNamewhen its a nested object这条修复要解决的是当 Drizzle 数据库实例不是顶层变量db而是被封装在嵌套对象中例如this.dataSource.db、this.database.db、this.getDataSource().db并且用户通过drizzleObjectName配置指定了内部对象名时规则无法正确识别该调用来自 Drizzle 对象从而导致误报把非 Drizzle 的delete()/update()当作 Drizzle 调用或漏报真正的 Drizzle 调用未被拦截。要理解这条修复必须先弄清楚drizzleObjectName选项与成员表达式MemberExpression解析的实现细节。二、两条规则与 drizzleObjectName 选项2.1 规则背景防止无 WHERE 的全表删除与全表更新eslint-plugin-drizzle 目前提供两条规则见 src/index.tsenforce-delete-with-where强制.delete()必须搭配.where()防止误删全表enforce-update-with-where强制.update().set()必须搭配.where()防止误改全表。两条规则的元数据声明一致type: problem、fixable: code并注册了一个可选的drizzleObjectName配置项其类型为string | string[]见 enforce-delete-with-where.ts 与 enforce-update-with-where.ts。2.2 drizzleObjectName 的三种形态drizzleObjectName用于告诉规则代码中哪个标识符才是 Drizzle 数据库实例从而避免把用户自定义类同样有delete()/update()方法的调用误判为违规。其判定逻辑集中在 src/utils/options.ts 的isDrizzleObjName函数中字符串形态typeof drizzleObjectName string时做精确相等比较例如{ drizzleObjectName: db }数组形态传入string[]时只要命中数组中任一名称即视为 Drizzle 对象特别地空数组[]等价于「不限制」任何对象名都会被命中drizzleObjectName.length 0直接返回true这也是默认行为默认值两条规则的defaultOptions均为[{ drizzleObjectName: [] }]意味着不配置时规则对任意对象上的delete()/update()都生效。{ rules: { drizzle/enforce-delete-with-where: [error, { drizzleObjectName: [db] }], drizzle/enforce-update-with-where: [error, { drizzleObjectName: db }] } }三、修复的核心嵌套对象的成员表达式检测3.1 修复前的缺陷isDrizzleObjsrc/utils/options.ts负责判断一个MemberExpression节点是否来自 Drizzle 对象。它逐层检查node.object的类型Identifier取node.object.name与配置比对MemberExpression取node.object.property.name与配置比对CallExpression取 callee 的name或property.name与配置比对。问题在于当 Drizzle 对象以多级嵌套形式出现时如this.dataSource.dbisDrizzleObj只检查了第一层成员表达式this.dataSource的属性名dataSource而未递归到内层db。此时如果用户配置的是drizzleObjectName: [db]dataSource不匹配规则就会认为这不是 Drizzle 调用从而漏报真正的db.delete()/db.update().set()危险操作。3.2 修复后的检测流程0.2.2 修复后检测链按「从外到内」的顺序逐层提取属性名只要任意一层命中配置的drizzleObjectName就判定为 Drizzle 对象。以this.dataSource.db.delete()为例外层成员表达式为this.dataSource.db调用delete的接收者其property.name为dbisDrizzleObj命中db与配置匹配判定为 Drizzle 对象触发规则同样地this.getDataSource().db、this.database.getDatabase()等链式嵌套也能被正确识别。这一点在 delete.test.ts 中有直接印证this.dataSource.db.delete({})在drizzleObjectName: [db]配置下被报告且错误消息中的drizzleObjName被解析为完整的this.dataSource.db。3.3 错误消息中的对象路径解析修复同时让错误提示更精准。规则在context.report中通过resolveMemberExpressionPathsrc/utils/ast.ts还原出完整的调用链文本用于构造类似下面这条可读性极强的提示见 enforce-update-with-where.tsWithout.where(...)you will update all the rows in a table. If you didnt want to do it, please usethis.dataSource.db.update(...).set(...).where(...)instead.resolveMemberExpressionPath会沿 AST 向上遍历把MemberExpression、CallExpression、Identifier、ThisExpression逐层拼接为字符串。从测试用例可以看到它支持的各种形态代码形态解析出的 drizzleObjNamedb.update({}).set()dbgetDatabase().update({}).set()getDatabase(...)this.dataSource.getDatabase(arg1, arg2).update({}).set()this.dataSource.getDatabase(...)this.getDataSource().db.update({}).set()this.getDataSource(...).db这些断言分别出现在 update.test.ts 与 delete.test.ts 中覆盖了this嵌套、方法链返回对象、带参数调用等多种真实编码场景。四、where状态跟踪规则的触发条件细节两条规则都通过模块级变量lastNodeName记录「上一次访问过的成员属性名」以判断.where()是否已经出现delete 规则enforce-delete-with-where.ts当访问到delete属性、且lastNodeName ! where时报告违规update 规则enforce-update-with-where.ts当访问到set属性、其外层是update(...)调用、且lastNodeName ! where时报告违规。因此合法的链式调用db.update().set().where()与db.delete().where()不会触发规则而db.update().set()、db.delete()、甚至db.update({}).set未调用都会被标记为错误——对应测试中的 valid/invalid 用例。注意lastNodeName是模块级状态两条规则分别在各自模块内维护互不干扰。五、安装与配置实战5.1 安装在项目根目录执行详见 readme.md# npm / yarn / pnpm / bun 任选其一 npm install eslint eslint-plugin-drizzle npm install -D typescript-eslint/eslint-plugin typescript-eslint/parsertypescript-eslint/parser是必要的——规则的RuleTester测试即基于它运行见 update.test.ts生产环境同样依赖它解析 TypeScript 语法。5.2 单条规则配置.eslintrc.ymlroot: true parser: typescript-eslint/parser parserOptions: project: ./tsconfig.json plugins: - drizzle rules: drizzle/enforce-delete-with-where: error drizzle/enforce-update-with-where: error5.3 推荐配置全量 / 推荐插件导出了all与recommended两套预设配置src/configs/recommended.ts二者目前等价均将两条规则设为errorroot: true extends: - plugin:drizzle/recommended parser: typescript-eslint/parser parserOptions: project: ./tsconfig.json plugins: - drizzle5.4 减少误报指定 drizzleObjectName当项目中存在自带delete()/update()方法的类时不配置drizzleObjectName会把它们的调用也判为违规。通过配置仅让 Drizzle 对象触发规则{ rules: { drizzle/enforce-delete-with-where: [error, { drizzleObjectName: [db] }], drizzle/enforce-update-with-where: [error, { drizzleObjectName: [db] }] } }配置后的行为差异如下来自 readme.md 与 delete.test.tsclass MyClass { public delete() { return {} } } const myClassObj new MyClass(); myClassObj.delete(); // 配置了 drizzleObjectName 后不再误报 this.database.db.delete(); // 嵌套对象0.2.2 修复后可被正确识别并报错六、从版本演进看修复脉络将 0.2.2 放入版本序列中可以更清楚地看到这条修复的价值0.2.0变更日志首发版本提供两条规则0.2.1变更日志完善 README、调整错误文案0.2.2变更日志修复嵌套对象下的drizzleObjectName检测补齐了成员表达式递归识别的能力0.2.3变更日志进一步覆盖「drizzleObjectName来自函数返回值」的场景并将isDrizzleObjName提取为公共函数消除重复代码。由此可见0.2.2 是插件检测能力从「仅识别顶层变量」走向「支持嵌套对象」的关键一步为后续对函数返回对象形态的支持奠定了基础。结语eslint-plugin-drizzle 0.2.2 的这条单行变更日志背后是对 MemberExpression 递归解析逻辑的一次实质增强它让drizzleObjectName在this.dataSource.db、this.getDataSource().db等嵌套对象场景下能够被正确命中既避免了危险的无where全表操作漏网也减少了自定义类方法调用的误报。对于在大型项目中将 Drizzle 实例封装在 Service、DataSource 等容器对象中的团队而言升级到 0.2.2 及以上版本并配合drizzleObjectName配置是构建「无 where 即报错」安全底线的高性价比方案。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考