DrewRidley/surrealguard

GitHub: DrewRidley/surrealguard

针对 SurrealQL 的静态分析与类型推断工具,在查询到达数据库前捕获字段、类型和图遍历错误,并为 Rust 和 TypeScript 提供编译期类型检查。

Stars: 2 | Forks: 0

# 🛡️ SurrealGuard ### 针对 SurrealQL 的静态分析与类型推断 在查询到达 SurrealDB *之前*捕获未知字段、类型不匹配和错误的图遍历—— 并在 **Rust** 和 **TypeScript** 中获得完全类型化的结果。 [![npm](https://img.shields.io/npm/v/@surrealguard/client?label=%40surrealguard%2Fclient&color=cb3837&logo=npm&logoColor=white)](https://www.npmjs.com/package/@surrealguard/client) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/DrewRidley/surrealguard/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-3b82f6)](#license) [**文档**](https://surrealguard.dev/docs/) · [**在线演示**](https://surrealguard.dev/#playground) · [**npm**](https://www.npmjs.com/org/surrealguard) · [**DESIGN.md**](docs/DESIGN.md)
SurrealGuard 将你的 `.surql` schema 和查询解析为带有跨度信息的类型化 AST, 推断每条语句的响应类型,并报告违反每个构造契约的行为。该引擎同时为 CLI、语言服务器、Rust proc-macro 以及一系列 TypeScript 包提供支持。 ## 为什么需要它 SurrealDB 在运行时非常宽松:跨类型比较会按类型排序而不是直接报错,强制转换会静默成功, 而拼写错误的字段只会返回 `NONE`。这正是 bug 隐藏的地方。SurrealGuard 是 **契约优先**的——每个构造都有一个契约(作者必须表达的含义才能使语句有意义), 并且分析器会报告违反该契约的行为,即使引擎本身能够正常执行该查询。 SurrealDB 自身的解析器在生成 AST 之前就丢弃了跨度信息,因此它无法为分析器或 编辑器工具提供支持。SurrealGuard 使用 tree-sitter 将其解析为带有跨度信息的 类型化 AST,并在此基础上运行所有分析。 ## 编译器即检查器 (Rust) ``` use surrealguard_rs::query; // Checked against your schema at compile time. A wrong table, unknown field, // bad arity, or kind mismatch is a `cargo check` error — no external step. let users = query!("SELECT name, age FROM user"); // users: Query> ← nameless, inferred ``` `query!` 在编译期间运行真正的分析器,将发现的问题转化为带有跨度信息的 `compile_error!`,然后根据推断出的响应类型生成结果类型——无需代码生成步骤, 无需语言服务器,也无需运行时获取 schema。将其指向 `schema/` 或 `migrations/` 目录(按顺序应用),它就能解析出真实的表和字段。`surql!` 是更轻量的形式: 检查查询,并展开为其文本。 ## 类型化查询,无需包装器 (TypeScript) ``` // One import: the generated file re-exports a ready client that IS a SurrealDB // `Surreal` (every SDK method) and loads the typed query registry. import { SurrealGuardClient } from "./surrealguard.generated"; // from `surrealguard generate` const db = new SurrealGuardClient(); await db.connect("ws://localhost:8000/rpc"); // SurrealDB returns one result per statement, so destructure the first result. const [users] = await db.query("SELECT name FROM user WHERE team = $team", { team: "red" }); // ^ result typed from the query text; params required + typed; wrong/missing params // are compile errors. Dynamic strings degrade to `unknown[]` and still run. ``` 框架适配器构建于响应式核心 (`@surrealguard/query`) 之上,该核心隐藏了 SSR 水合和实时查询的生命周期: ``` {#each $users.data as user (user.id)}
  • {user.name}
  • {/each} ``` `LIVE SELECT` 会开启一个共享的、基于引用计数的订阅,并根据记录 id 对 变更通知进行调节;`@surrealguard/next` 通过 `useLiveQuery` hook 提供相同的功能。 ## 分析内容 - **全语句覆盖** —— SELECT(projections、图遍历、FETCH/SPLIT/GROUP/OMIT), 六种 mutations,RELATE,LET/RETURN/IF/FOR/blocks,transactions, DEFINE/REMOVE/ALTER,LIVE SELECT/KILL 等。 - **类型推断** —— 响应类型作为上游的 `surrealdb_types::Kind`:已知行的 闭合 object literals,来自 IF/ELSE 的 unions,record-link 和 graph-edge 形状,完整的内置函数表以及 `fn::` 声明,closure 和 subquery 推断, 以及常量值求值。 - **包含约 80 种诊断的契约目录**,分为多个系列(1xxx schema 引用, 2xxx 类型,3xxx 图,4xxx 语句误用,5xxx 函数,6xxx 参数, 7xxx lints,8xxx 版本兼容性)。严重性是每种发现固有的;使用者在其边界 应用策略(将警告视为错误、lint 级别),风格类似于 rustc。 - **参数约束** —— 源文件读取的每个 `$param` 都会根据其使用情况导出对应的 类型和值域(`UPDATE user SET age = $age` → `age: int`; `LIMIT $n` → 非负 int)。 - **精确到字节的跨度信息**,附加在每项发现上,用于编辑器波浪线提示。 ## 使用方式 - **CLI** —— `surrealguard check` 分析工作区(`--json` 用于机器输出; 退出码反映应用策略后的错误);`surrealguard generate` 生成 TypeScript 类型;`surrealguard init` 编写初始配置。 - **编辑器 (LSP)** —— `surrealguard-lsp` 通过 stdio 为 `.surql` 文件*以及* 嵌入在宿主文件中的 SurrealQL(TypeScript, Svelte, Vue, Astro)发布诊断信息—— 波浪线提示会精确地落在你的内联查询中的具体 token 上。 - **Rust** —— `surrealguard-rs` crate 重新导出了 `query!` / `surql!` 宏。 - **TypeScript** —— `@surrealguard/client`、`@surrealguard/query`、 `@surrealguard/next`、`@surrealguard/svelte`。 ## 项目布局 ``` surrealguard/ ├── crates/ │ ├── syntax/ # tree-sitter parsing, typed span-carrying AST, lowering │ ├── diagnostics/ # finding types, code catalog, severity/lint policy │ ├── workspace/ # schema index, analyzers, inference, analysis pipeline │ ├── codegen/ # Kind → TypeScript generation │ ├── embed/ # embedded-SurrealQL extraction from host files │ ├── macros/ # the surql! / query! proc-macros │ ├── rs/ # surrealguard-rs runtime (typed results) │ ├── cli/ # the `surrealguard` binary │ └── lsp/ # the `surrealguard-lsp` binary ├── packages/ # @surrealguard/{client,query,next,svelte} (pnpm workspace) └── docs/ # DESIGN.md + design plans (incl. the diagnostic catalog) ``` ## 安装 **TypeScript**(已发布): ``` npm i @surrealguard/client # + @surrealguard/{query,next,svelte} ``` **Rust / CLI**(在 crates.io 版本最终确定之前从源码构建): ``` cargo install --path crates/cli surrealguard init && surrealguard check ``` 工作区会按顺序分析每个 `.surql` 源文件,因此 schema 定义对于 后续的查询是可见的。 ## 状态 该引擎(类型化 AST、完整的推断、约 80 种契约诊断、参数约束)、 CLI、LSP、Rust 的 `surql!` / `query!` 宏以及 TypeScript 包 均已构建完成,并且 CI 测试通过。 - **npm** —— `@surrealguard/{client,query,next,svelte}` **已发布** (0.2.x)。 - **Grammar** —— 优先级修复和功能增加已**合并至上游** [`surrealdb/surrealql-tree-sitter`](https://github.com/surrealdb/surrealql-tree-sitter) 仓库中。 - **crates.io** —— Rust crates(`surrealguard`、`surrealguard-rs`)即将推出。 有关架构和路线图,请参阅 [`docs/DESIGN.md`](docs/DESIGN.md)。 ## 许可证 根据你的选择,受 [Apache License, Version 2.0](LICENSE-APACHE) 或 [MIT license](LICENSE-MIT) 许可。除非你明确声明,否则你出于包含在本项目中的目的 而有意提交的任何贡献(如 Apache-2.0 许可证中所定义),均应按上述方式进行双重许可, 不附加任何额外的条款或条件。
    标签:AST解析, Rust, SurrealDB, SurrealQL, TypeScript, 云安全监控, 可视化界面, 安全插件, 暗色界面, 类型推断, 网络流量审计, 语言服务器协议, 通知系统, 静态分析