支持 CRDT 的 Type-Safe 实时协作图数据库
摘要
Codemix 开源了 @codemix/graph,这是一款具备 TypeScript 原生模式验证、基于 CRDT 的图数据库,并通过 Yjs 实现实时离线优先同步。
查看缓存全文
缓存时间: 2026/04/21 11:19
@codemix/graph - codemix
来源:https://codemix.com/graph
航线演示
全球航线演示
将真实航线快照加载到图中,并用 TypeScript 查询。
在线演示
把头像贴到墙上
由 @codemix/graph 与 @codemix/y-graph-storage 驱动——真正的图数据库,通过 Yjs CRDT 在所有打开的标签页之间同步。添加自己、拖动头像、画连线。
安装
从 npm 安装——无原生依赖,任何支持 Node 或打包工具的环境都能跑。
$ pnpm add @codemix/graph
**注意:**这是 alpha 阶段软件。我们在 codemix 生产环境使用,已能满足自身需求,但用于你自己的数据时请谨慎。
定义模式
用普通对象描述顶点、边与索引。属性类型会贯穿所有查询、遍历与变更——无需强制转换,无运行时报错。
import { Graph, GraphSchema, InMemoryGraphStorage } from "@codemix/graph";
import { z } from "zod";
const schema = {
vertices: {
User: {
properties: {
email: { type: z.email(), index: { type: "hash", unique: true } },
name: { type: z.string() },
},
},
Repo: {
properties: {
name: { type: z.string() },
stars: { type: z.number() },
},
},
},
edges: {
OWNS: { properties: {} },
FOLLOWS: { properties: {} },
},
} as const satisfies GraphSchema;
const graph = new Graph({ schema, storage: new InMemoryGraphStorage() });
- → 任意标准模式库 —— Zod、Valibot、ArkType 或自定义。
- → 每次变更都校验 ——
addVertex、addEdge、updateProperty时都会检查属性。 - → 索引随声明创建 —— 哈希、B 树、全文;惰性构建,增量维护。
添加数据
通过图实例添加顶点与边。属性参数在编译时与运行时都会按模式校验。
// 添加顶点 —— 参数按标签的属性模式进行类型检查
const alice = graph.addVertex("User", { name: "Alice", email: "[email protected]" });
const bob = graph.addVertex("User", { name: "Bob", email: "[email protected]" });
const myRepo = graph.addVertex("Repo", { name: "my-repo", stars: 0 });
// 添加边
graph.addEdge(alice, "OWNS", myRepo, {});
graph.addEdge(bob, "FOLLOWS", alice, {});
// 读取属性 —— 类型来自模式
alice.get("name"); // string
myRepo.get("stars"); // number
// 就地更新
graph.updateProperty(myRepo, "stars", 42);
// 或通过元素自身
myRepo.set("stars", 42);
编写类型安全查询
Gremlin 风格的遍历 API —— 步骤名熟悉,但每个标签、属性键、跳转都由 TypeScript 按模式校验。
开始遍历
import { GraphTraversal } from "@codemix/graph";
const g = new GraphTraversal(graph);
for (const path of g.V().hasLabel("User")) {
path.value.get("name"); // string ✓
path.value.get("email"); // string ✓
}
按属性过滤
// 精确匹配或谓词
const [alice] = g.V()
.hasLabel("User")
.has("email", "[email protected]");
const seniors = g.V()
.hasLabel("User")
.where((v) => v.get("name").startsWith("A"));
沿边遍历
// 沿 User → Repo 的 OWNS 边
for (const path of g.V()
.hasLabel("User")
.has("email", "[email protected]")
.out("OWNS").hasLabel("Repo")) {
path.value.get("stars"); // number —— 来自 Repo 模式
}
标记与选择
// 在多跳处捕获顶点并一起投影
for (const { user, repo } of g.V()
.hasLabel("User").as("user")
.out("FOLLOWS")
.out("OWNS").hasLabel("Repo").as("repo")
.select("user", "repo")) {
console.log(
user.value.get("name"), // string
repo.value.get("stars"), // number
);
}
离线优先同步与实时协作
把 InMemoryGraphStorage 换成 YGraph,整张图就活在 Yjs (https://yjs.dev/) CRDT 文档里。所有遍历、Cypher 查询、索引照常工作——只是额外获得了无冲突同步。
接入 provider
import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";
import { YGraph } from "@codemix/y-graph-storage";
const doc = new Y.Doc();
const graph = new YGraph({ schema, doc });
// 连接任意 Yjs provider —— 同步自动完成。
// 每个加入房间的节点都会看到同一张图。
const provider = new WebsocketProvider("wss://my-server", "graph-room", doc);
订阅细粒度变更
// 本地与远程变更都会触发事件
const unsubscribe = graph.subscribe({
next(change) {
// change.kind 为以下之一:
// "vertex.added" | "vertex.deleted"
// "edge.added" | "edge.deleted"
// "vertex.property.set" | "vertex.property.changed"
console.log(change.kind, change.id);
},
});
实时查询
// 包装任意遍历,当结果集可能变化时重新触发
const topRepos = graph.query((g) =>
g.V().hasLabel("Repo").order("stars", "desc").limit(10)
);
const unsubscribe = topRepos.subscribe({
next() {
for (const path of topRepos) {
console.log(path.value.get("name"), path.value.get("stars"));
}
},
});
// 在其他地方添加或更新 Repo —— 哪怕是远程节点 ——
// 也会自动触发订阅者。
graph.updateProperty(myRepo, "stars", 99);
协作属性类型
import { ZodYText, ZodYArray } from "@codemix/y-graph-storage";
import { z } from "zod";
// 在模式中声明 Y.Text / Y.Array / Y.Map 属性
const schema = {
vertices: {
Document: {
properties: {
title: { type: ZodYText }, // 协作字符串
tags: { type: ZodYArray(z.string()) }, // 协作数组
},
},
},
edges: {},
} as const satisfies GraphSchema;
// 普通值自动转换 —— 无需手动构造 Y.*
const doc = graph.addVertex("Document", { title: "Hello", tags: ["crdt"] });
// 就地变更 —— 所有节点无冲突地看到变化
doc.get("title").insert(5, ", world");
doc.get("tags").push(["graph"]);
面向 API 与 LLM 的 Cypher 查询
同一张图也支持类 Cypher 的字符串查询语言——适合通过 MCP 服务器向 LLM 暴露数据,或让外部客户端无需引入遍历库即可执行即席查询。
解析并执行
import { parseQueryToSteps, createTraverser } from "@codemix/graph";
const { steps, postprocess } = parseQueryToSteps(`
MATCH (u:User)-[:OWNS]->(r:Repo)
WHERE r.stars > 100
RETURN u.name, r.name
ORDER BY r.stars DESC
LIMIT 10
`);
const traverser = createTraverser(steps);
for (const row of traverser.traverse(graph, [])) {
console.log(postprocess(row));
// { u: { name: "Alice" }, r: { name: "my-repo" } }
}
参数化查询
// 传递参数,避免字符串拼接
const { steps, postprocess } = parseQueryToSteps(`
MATCH (u:User { email: $email })-[:OWNS]->(r:Repo)
RETURN r.name, r.stars
`);
const traverser = createTraverser(steps);
const rows = Array.from(
traverser.traverse(graph, [{ email: "[email protected]" }])
).map(postprocess);
变更
// 支持 CREATE、MERGE、SET、DELETE
const { steps } = parseQueryToSteps(`
MATCH (r:Repo { name: $name })
SET r.stars = r.stars + 1
`);
createTraverser(steps).traverse(graph, [{ name: "my-repo" }]);
// 强制只读 —— 遇到写子句会抛出 ReadonlyGraphError
const { steps: safeSteps } = parseQueryToSteps(query, { readonly: true });
许可与历史
本包采用 MIT 许可。
最初由 Charles Pick(https://x.com/c_pick)作为研究项目编写,他是 codemix(https://codemix.com/)创始人,也是臭名昭著的 ts-sql(https://github.com/codemix/ts-sql)演示作者。后来我们在构建 codemix(https://codemix.com/)时需要结构化知识图谱,于是改造了代码,加入 Y.js(https://yjs.dev/)支持,再后来 Opus 4.5 又添加了类 Cypher 查询语言。
在 GitHub 上给我们加星(https://github.com/codemix/graph)
顺便看看
产品唯一真相源。面向人类与 AI。
codemix 捕捉你真正的“意图”——业务领域、用户流程、概念、约束——并自动与代码库保持同步。
通过聊天、图表或协作编辑来变更产品。让编码代理在开发与代码审查中拥有真正的理解。团队中的每个代理共享同一份上下文。
从零创造,或导入现有代码库即可开始。
从零构建全新产品
免费试用 codemix,无需信用卡。
相似文章
colbymchenry/codegraph
CodeGraph 是一个开源工具,为代码库创建预索引的知识图谱,使 Claude Code 的探索代理能够即时查询符号关系和调用图,将工具调用次数减少高达 96%,探索时间减少 77%。
在遇到 LangGraph 天花板后,我构建了自己的智能体运行时——将 UI 作为图节点,Postgres 持久化,零编排成本
作者介绍了 cascaide,这是一个全栈智能体运行时和 AI 编排框架,使用 TypeScript 编写,可在任何支持 JS/TS 的环境运行。它提供 UI 作为图节点、持久化 Postgres 检查点、零编排成本,并且设计为可自托管,无供应商锁定。
@yoheinakajima:我很激动地开源 Active Graph:一个事件溯源的反应式图运行时,用于长时间运行的智能体事件/日志等
Yohei Nakajima 开源了 Active Graph,这是一个基于事件溯源的反应式图运行时,用于长时间运行的智能体,提供持久化状态、分支与差异智能体运行以及完全可审计性,代表了智能体架构的新范式。
Show HN: HelixDB – 基于对象存储的图数据库
HelixDB 是一个用 Rust 构建的图-向量数据库,专为知识图谱和 AI 记忆设计,提供统一平台支持图、向量、键值、文档和关系型数据模型,并配有便于本地和云端部署的工具。
@daleverett: https://x.com/daleverett/status/2055332581659566288
pgGraph 是一个高性能、开源图遍历扩展,专为 PostgreSQL 设计,使用 Rust 编写,旨在让 AI 代理能够快速执行关系查询,而无需将数据迁移到单独的图数据库中。