尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

用 Splinter 为 Supabase 数据库 Schema 做静态检查:liam 项目 `@liam-hq/db` 的 Lint 集成实战

发布时间:2026/9/18 20:12:44

资讯中心
01
ARTICLE

用 Splinter 为 Supabase 数据库 Schema 做静态检查:liam 项目 `@liam-hq/db` 的 Lint 集成实战

用 Splinter 为 Supabase 数据库 Schema 做静态检查:liam 项目 `@liam-hq/db` 的 Lint 集成实战
用 Splinter 为 Supabase 数据库 Schema 做静态检查liam 项目liam-hq/db的 Lint 集成实战【免费下载链接】liamAutomatically generates beautiful and easy-to-read ER diagrams from your database.项目地址: https://gitcode.com/GitHub_Trending/li/liam在 liam一个自动从数据库生成美观易读 ER 图的工具这样的项目中Supabase 数据库 schema 的稳定性与安全性直接决定了上层应用的可靠性。本文以 frontend/internal-packages/db/scripts/db-lint/README.md 为核心结合仓库中run-splinter.sh、splinter.sql、package.json 与 database-ci.yml 的源码级实现完整讲解如何在本地与 CI 中运行 Splinter 数据库 lint、如何解读 21 条检查规则以及如何利用调试开关排查问题。读完本文你将能在自己的 Supabase 项目中落地一套规则驱动、CI 强制、可本地复现的 schema 质量防线。Splinter 是什么为什么 liam 需要它Splinter 是 Supabase 官方维护的一套数据库 lint 检查工具它以一段纯 SQL 的形式分发核心逻辑全部写在splinter.sql中通过查询 PostgreSQL 的系统目录pg_catalog来发现 schema 层面的问题覆盖性能与安全两大类主题——例如外键缺少覆盖索引、RLS行级安全未开启、策略引用了可被用户篡改的user_metadata等。liam 的liam-hq/db包以 supabase/ 下的迁移脚本管理 schema任何 schema 缺陷比如忘记给外键加索引、新建表未开 RLS都会在 ER 图生成、API 查询链路上放大。因此该包在scripts/db-lint/目录中内置了 Splinter 集成并把它接入 Pull Request 的 CI 流程让问题在合并前就被拦截。目录中只有三个文件职责清晰文件职责splinter.sql官方 Splinter 规则的完整合集当前文件实际包含 21 条检查README 标注为 15 条run-splinter.sh薄封装脚本执行查询、格式化输出、暴露调试辅助开关README.md使用指南即本文所依据的文档规则集一览21 条检查覆盖性能与安全splinter.sql的头部注释splinter.sql明确标注了其来源为官方 Splinter 仓库、采用 MIT 许可证并以set local search_path 开头避免搜索路径干扰。整个文件是一个大型union all查询每个分支输出统一结构的行字段依次为name、title、level、facing、categories、description、detail、remediation、metadata、cache_key。当前规则集共 21 条按检查级别和类别归纳如下规则名级别类别检查内容unindexed_foreign_keysINFOPERFORMANCE外键约束缺少覆盖索引可能拖慢查询auth_users_exposedERRORSECURITYauth.users通过视图/物化视图暴露给 anon 或 authenticated 角色auth_rls_initplanWARNPERFORMANCERLS 策略中对current_setting()/auth.function()逐行重复求值应改为(select ...)形式no_primary_keyINFOPERFORMANCE表没有主键unused_indexINFOPERFORMANCE索引从未被扫描idx_scan 0可考虑删除multiple_permissive_policiesWARNPERFORMANCE同一角色同一操作存在多条 permissive 策略policy_exists_rls_disabledERRORSECURITY表创建了 RLS 策略但未启用 RLSrls_enabled_no_policyINFOSECURITY表启用了 RLS 但没有任何策略duplicate_indexWARNPERFORMANCE存在两条完全相同的索引定义security_definer_viewERRORSECURITY视图以SECURITY DEFINER定义绕过查询者的权限与 RLSfunction_search_path_mutableWARNSECURITY函数未固定search_path存在搜索路径篡改风险rls_disabled_in_publicERRORSECURITY暴露给 PostgREST 的 schema 中表未启用 RLSextension_in_publicWARNSECURITY扩展被安装到publicschemarls_references_user_metadataERRORSECURITYRLS 策略引用了用户可编辑的 Supabase Authuser_metadatamaterialized_view_in_apiWARNSECURITY物化视图对 anon/authenticated 角色可 SELECT物化视图不支持 RLSforeign_table_in_apiWARNSECURITY外部表暴露在 API 中外部表不遵守 RLSunsupported_reg_typesWARNSECURITY在pg_catalog之外使用reg*类型列会阻碍pg_upgradeinsecure_queue_exposed_in_apiERRORSECURITYpgmq的队列表q_%未开 RLS 且暴露在 API 中table_bloatINFOPERFORMANCE表膨胀超过阈值bloat 70.0且浪费空间 200MBfkey_to_auth_uniqueERRORSECURITY用户自定义外键指向authschema 的 unique 约束extension_versions_outdatedWARNSECURITY扩展版本落后于默认推荐版本几个值得注意的实现细节security_definer_view有 PostgreSQL 版本前提查询中带有substring(pg_catalog.version() from PostgreSQL ([0-9])) 15的判断因为security_invoker选项在 PG 15 才引入。这与 supabase/config.toml 中major_version 15的本地环境设定一致。table_bloat有明确的过滤阈值只有bloat 70.0且raw_waste 200 MB才报告避免噪音splinter.sql。unused_index做了大量排除idx_scan 0且非唯一、非主键、非扩展依赖表防止误报splinter.sql。几乎所有规则都维护了排除名单pg_catalog、auth、storage、extensions等系统/托管 schema 一律跳过聚焦用户自己的 schema。每条规则都携带remediation修复指引字段运行脚本会将其打印出来例如fkey_to_auth_unique的修复建议是删除引用 auth schema 的外键约束table_bloat则提示vacuum full会带来停机时间、并建议调整 autovacuum 参数。本地运行三条命令打通README 给出的本地运行方式如下在frontend/internal-packages/db目录下cd frontend/internal-packages/db pnpm supabase:start # 启动本地 Supabase 栈 SPLINTER_DEBUG1 pnpm db:lint # DATABASE_URL 默认指向本地栈 pnpm supabase:stop # 可选结束后关闭栈这三个命令分别对应 package.json 中的supabase:start、supabase:stop与db:lint脚本。关键点在于db:lint脚本的完整定义db:lint: bash -lc DATABASE_URL${DATABASE_URL:-postgresql://postgres:postgreslocalhost:54322/postgres} ./scripts/db-lint/run-splinter.sh也就是说即使你不显式设置DATABASE_URL脚本也会回退到本地 Supabase 栈的连接串localhost:54322与 supabase/config.toml 中[db] port 54322一致。如果你希望检查其他数据库实例只需覆盖环境变量DATABASE_URLpostgresql://user:passwordhost:port/dbname pnpm db:lint如果你在 monorepo 工作区根目录可以用 pnpm 的 filter 语法直接对liam-hq/db包执行SPLINTER_DEBUG1 pnpm -F liam-hq/db db:lint包装脚本内部run-splinter.sh的执行流水线run-splinter.shrun-splinter.sh是理解整个 lint 流程的最佳入口它的执行流水线如下前置校验以set -e开头先检查DATABASE_URL是否设置、splinter.sql是否存在缺失即红色报错退出run-splinter.sh。执行查询将splinter.sql全文作为一条查询交给psql使用-t -A -F$\t输出无表头、以 Tab 分隔的结果临时写入文件run-splinter.sh。退出码处理psql非零退出时输出原始错误并退出否则继续。问题计数用awk -F$\t $1 ! 统计第一列规则名非空的行数作为问题总数run-splinter.sh。分级渲染逐行按level字段分流——ERROR红色、WARN黄色、INFO蓝色打印[级别] 标题、detail详情以及可选的 Remediation修复指引run-splinter.sh。汇总与退出末尾输出 Errors / Warnings / Info 三项计数只要任一级别存在问题就以exit 1失败run-splinter.sh。这里体现了该项目的一个关键策略ERROR、WARN、INFO 一律视为失败。这不是脚本的默认行为而是仓库有意的严格选择——README 明确说明Currently, ERROR, WARN, and INFO findings all fail the job and block the build。调试辅助SPLINTER_DEBUG1能告诉你什么当结果异常比如输出被截断、解析错位、psql 报错但信息不够时打开调试开关SPLINTER_DEBUG1 pnpm -F liam-hq/db db:lint脚本会额外打印四类信息run-splinter.sh原始输出的总行数wc -l前 5 行原文第一行的十六进制转储od -An -tx1用于排查 Tab 分隔符、不可见字符等编码问题psql的退出状态码。之所以需要 hex dump是因为脚本依赖 Tab 分隔符做字段解析任何混入的空格、换行或编码问题都会让渲染错乱调试模式可以在 CI 与本地之间做快速对照。CI 集成数据库质量门禁Splinter 的 CI 入口是 .github/workflows/database-ci.yml。该工作流的触发条件覆盖三种场景PR 触发当 PR 改动frontend/internal-packages/db/**或工作流文件本身时运行merge_group合并队列merge queue场景workflow_dispatch支持手动触发。Run Splinter Lint步骤database-ci.yml的执行内容与本地完全一致- name: Run Splinter Lint run: pnpm -F liam-hq/db db:lint env: DATABASE_URL: postgresql://postgres:postgreslocalhost:54322/postgres SPLINTER_DEBUG: 1该 job 同时承担了 PGTap 数据库测试supabase test db整体流程是actions/checkout→supabase/setup-cli→supabase start启动本地栈 →pnpm-setup→ 运行 Splinter lint → 加载setup-testing.sql→ 运行 PGTap 测试。也就是说lint 与测试共享同一个本地 Supabase 实例任何 ERROR/WARN/INFO 发现都会让 job 失败、阻塞 PR 合并。扩展与维护如何增删规则run-splinter.sh的输出解析对字段顺序是敏感的如果你基于此集成扩展自己的规则需要遵守约定在splinter.sql的union all中追加一个select分支输出顺序必须与既有规则一致name, title, level, facing, categories, description, detail, remediation, metadata, cache_keylevel必须是ERROR/WARN/INFO之一脚本的case分支与配色映射依赖它run-splinter.shremediation允许为null脚本会跳过null值的打印metadata使用jsonb_build_object构造便于机器消费的结构化信息cache_key建议用规则名_对象标识的格式拼接保证每个问题实例可去重、可追踪。若想临时跳过某条规则也可以直接编辑splinter.sql中对应分支但要注意保持search_path 的设置避免依赖会话级搜索路径导致结果漂移。小结liam 在liam-hq/db中落地了一套小而完整的数据库 lint 方案以官方 Splinter 的纯 SQL 规则集为检查引擎用一个 120 行左右的 Bash 脚本完成执行、分级渲染与退出码控制再通过 pnpm 脚本与 GitHub Actions 实现本地一键复现、CI 强制拦截。对任何以 Supabase/PostgreSQL 为存储、且希望把 schema 质量前置到开发流程中的项目来说这套组合splinter.sql run-splinter.sh database-ci.yml都是可以直接借鉴的范本。【免费下载链接】liamAutomatically generates beautiful and easy-to-read ER diagrams from your database.项目地址: https://gitcode.com/GitHub_Trending/li/liam创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。