@aurelienbn/oxlint-plugin-cloudflare (英语)
7 关于云花板工人、耐用物体和工作流程的克林特规则:检查并通过的bugs wrangler deploy,然后在真实流量下失败.
[注] 释放候选人. 还没有消费者校正过.
pnpm add -D @aurelienbbn/oxlint-plugin-cloudflare oxlint # oxlint >=1.82.0 <2.0.0
{
"jsPlugins": ["@aurelienbbn/oxlint-plugin-cloudflare"],
"rules": {
"cloudflare/no-module-scope-request-state": "error",
"cloudflare/no-interpolated-sql": "error",
"cloudflare/workflow-deterministic-steps": "error",
"cloudflare/no-detached-execution-context-method": "error",
"cloudflare/durable-object-init-concurrency": "error",
"cloudflare/mysql2-disable-eval": "error",
"cloudflare/timing-safe-secret-compare": "error"
}
}
无预设. 一个自定义 : mysql2-disable-eval 添加 disableEval: true 到选项对象正文;所有其他规则只报告.
什么火吗
const client = new Client(env.HYPERDRIVE.connectionString); // ❌ no-module-scope-request-state
export default {
async fetch(request, env, ctx) {
const { waitUntil } = ctx; // ❌ no-detached-execution-context-method: throws "Illegal invocation"
await env.DB.prepare(`SELECT * FROM users WHERE id = ${id}`).first(); // ❌ no-interpolated-sql
await env.DB.prepare("SELECT * FROM users WHERE id = ?").bind(id).first(); // ✅
},
};
class Sync extends WorkflowEntrypoint {
async run(event, step) {
await step.do(`sync ${Date.now()}`, async () => {}); // ❌ workflow-deterministic-steps: never replays from cache
const id = await step.do("make id", async () => crypto.randomUUID()); // ✅
}
}
每项规则的确切触发因素和范围
| 规则 | * 开火 | 匹配/ QQ 跳过 |
|---|---|---|
no-module-scope-request-state | a TCP 客户端建在模块范围(pg Client编号 :Pool, (中文(简体) ), postgres(), mysql2 (英语) createConnection编号 :createPool编号 :createPoolCluster, (中文(简体) ), drizzle 从 node-postgres编号 :postgres-js编号 :mysql2); 模块-镜像变量 指定、更新、删除或由 push编号 :set编号 :add/... 在任何函数内 | 只有工人模块:导入 cloudflare:workers,或默认导出处理器对象。 QQ 类字段( Dable Object state), Drizzle D1/ HTTP 驱动程序, Prisma( 安全取决于适配器), 不属于 Worker 模块的辅助模块 |
no-interpolated-sql | 模板字义或 + 以运行时值连接为 SQL env.X.prepare 编号 : env.X.exec (另见: this.env, (中文(简体) ), c.env页:1 const db = env.X (别名)或 <x>.sql.exec 编号 : sql.exec页:1 const 持有此 SQL | 内插字和 const 字节(表名),标记模板,例如 this.sql`...` |
workflow-deterministic-steps | Date.now(), (中文(简体) ), Math.random(), (中文(简体) ), performance.now(), (中文(简体) ), crypto.randomUUID(), (中文(简体) ), crypto.getRandomValues()无参数 new Date() 在一个 step.do 编号 : sleep 编号 : sleepUntil 编号 : waitForEvent 名称,或 run() 外部a step.do 回调 | run(event, step) 扩展的类 WorkflowEntrypoint 从 cloudflare:workers。 。 。 Promise.race 编号 : Promise.any (未选中) 向助手函数传递的步骤 |
no-detached-execution-context-method | waitUntil 编号 : passThroughOnException 已解结构(包括在参数中),或在无调用的情况下阅读,并存储、通过、返回或放置在对象/阵列中 | ⏭️ .bind(ctx), (中文(简体) ), .call(ctx),可选的电话, 真相检查, 独立 waitUntil 导出 cloudflare:workers |
durable-object-init-concurrency | 在一个 DurableObject 构造器 : fetch编辑 storage.get编号 :put编号 :list编号 :delete编号 :transaction/报警电话,Aync IIFE,或 this.<asyncMethod>(),在召回器外;在任意 blockConcurrencyWhile 回调 : fetch 或I/O方法对 env 约束 | qq 同步 storage.sql.exec 财务报告和审定财务报表 storage.kv晚点再打. env.MY_DO.get(id) 在回调中报告,尽管它只建了根 |
mysql2-disable-eval | 用于 mysql2 的选项对象文字 createConnection 编号 : createPool 编号 : createPoolCluster 无 disableEval,或具有非字面值 true | 工人模块或选项读取 env.X (无) process.env. QQ 选项带有分布,选项通过标识符或URI传递. 修补插入 disableEval: true 只有在财产不存在时 |
timing-safe-secret-compare | === 编号 : !== 编号 : == 编号 : != 一方是或模板嵌入的地方, env.<NAME> 与名称匹配 SECRET, (中文(简体) ), TOKEN, (中文(简体) ), PASSWORD, (中文(简体) ), PASSPHRASE, (中文(简体) ), API_KEY, (中文(简体) ), PRIVATE_KEY, (中文(简体) ), SIGNING_KEY, (中文(简体) ), SIGNATURE, (中文(简体) ), CREDENTIAL | 与 undefined, (中文(简体) ), null, (中文(简体) ), "", (中文(简体) ), typeof· ; process.env |
没有运出,谁拥有它
| 关切 | 拥有者 |
|---|---|
| 期待已久的承诺、RPC呼吁和步骤 | 类型 typescript/no-floating-promises 在严格的预设中 |
陈旧或手写 Env 类型 | wrangler types --check; 手写 Env 没有声音同步触发器 |
Date.now() 在警报中 | 没有规则: setAlarm(Date.now() + n) 正确缩写 |
| 产品选择( KV vs D1 vs DO, 队列 vs Workflows) Name | 云花镇 workers-best-practices 财务报告和审定财务报表 durable-objects 技能 |
| cloudflare接收器外的原始 SQL | eslint-plugin-sql no-unsafe-query |
资信: 每个规则都独立执行来自 Cloudflare 的开发者文档( 工人最佳做法, 持久对象规则, 工作流程规则, D1, 持久对象 SQLite 存储, Hyperdrive 驱动页) 的引导; 没有复制文档文本或代码 .
登记的合同库存
从软件包导出 pnpm catalog. 规则特定选项和限制在上文和源测试中都有描述.
| 规则/检查 | 触发或审查范围 |
|---|---|
durable-object-init-concurrency | 要求持久对象构建器(存储读取、取取取、合成方法或IIFEs)的同步工作在ctx.block ConteneralWhile () 内运行,并禁止在块Conteneral()回调内取取取或绑取调用. |
mysql2-disable-eval | 需要 DisableEval: 在传递到 mysql2 的对象- literal 选项中的真实性 创建 Connection / 创建Pool / 在 Worker 代码中创建PoolCluster . |
no-detached-execution-context-method | 强制解构 waitUntil / pass Trough OnExcusement 从执行语境中, 或通过, 存储, 或者在没有接收器的情况下返回它们 . |
no-interpolated-sql | 无效模板- 升值插入或字符串将运行时间值连接到 SQL 中, 传递到 D1 准备( ) / exec( ) 或 持久对象 sql. exec (); 代替绑定参数 . |
no-module-scope-request-state | 在 Worker 模块范围强制每个请求状态:在模块范围构建的 TCP 数据库客户端(pg, postgres, mysql2, 其 Drizzle 驱动程序),以及从一个函数内部指定或变异的模块范围变量. |
timing-safe-secret-compare | 活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活. |
workflow-deterministic-steps | Forbid Date.now (), Math.random (), perforce.now (), crypto.randomUID (), crypto.getRandomValues () 和 Workflow step names () 中的新日期(), 或Workflow Entrypoint.run () 中任何一步外的地址. do () 回调 . |
信用概念
- https://developers.cloudflare.com/d1/worker-api/d1-数据库/ (激励;独立执行)
- https://developers.cloudflare.com/可持久-objects/api/sqlite-storage-api/ 互联网档案馆的存檔,存档日期2014-12-22 (激励;独立执行)
- https://developers.cloudflare.com/可持久对象/最佳实践/可持久对象的规则/ (激励;独立执行)
- https://developers.cloudflare.com/hyperdrive/examples/connect-to-mysql/mysql-drivers-和-librarys/mysql2/ 互联网档案馆的存檔,存档日期2007-12-2 (激励;独立执行)
- https://developers.cloudflare.com/hyperdrive/examples/接通-postgres/postgres-drivers-和-library/node-postgres/ 互联网档案馆的存檔,存档日期2013-12-21 (激励;独立执行)
- https://developers.cloudflare.com/工人/最佳做法/工人-最佳做法/ (激励;独立执行)
- https://developers.cloudflare.com/workflows/building/rules-of-workflows/ 互联网档案馆的存檔,存档日期2014-12-21 (激励;独立执行)