@undefineds.co/drizzle-solid
v0.3.16
Published
Drizzle ORM adapter for Solid Pods
Readme
drizzle-solid
English version: README.md
drizzle-solid 用类型化 schema 和 Drizzle 对齐的开发体验,把应用自有数据存进 Solid Pod。
适合在你需要下面这些能力时使用:
- 用 TypeScript schema 描述 Pod 数据
- 用
base和 base-relative resource id 明确声明数据布局 - 在
pod()和drizzle()两种 API 风格之间选择 - 通过 base-relative id 或 IRI 精确读写单个资源
- 在后端提供查询能力时走 SPARQL 读取
它擅长什么
- 应用自有数据存储在你的 Pod 或用户 Pod 中
- 对已知资源布局做类型化 CRUD
- 从
drizzle-orm逐步迁移,而不假装 Pod 就是 SQL 表 - 使用 IRI、文档、链接、发现、通知、联邦等 Pod 原生概念
它不打算做什么
- 通用 RDF 图探索工具
- 所有 Solid 后端上的完整 SQL / 数据库能力对齐
- 隐藏 Pod 边界、权限或网络成本
- raw SQL 优先的抽象层
安装
yarn add @undefineds.co/drizzle-solid drizzle-orm
# 可选:当你的应用需要内置 SPARQL 引擎时再安装
yarn add @comunica/query-sparql-solidnpm install @undefineds.co/drizzle-solid drizzle-orm
# 可选:当你的应用需要内置 SPARQL 引擎时再安装
npm install @comunica/query-sparql-solid@comunica/query-sparql-solid 是可选 peer dependency。
当前支持范围:
- 支持:
@comunica/query-sparql-solid4.x - 当前不在支持矩阵中:
3.x
如果宿主运行时已经自带 Comunica,就注入那一份,不要再装第二份。
选择 API 风格
pod(session)
适合新代码,或者你希望 API 直接体现 Solid 语义:
collection(table)entity(resource, iri)bind(schema, options)sparql(query)
drizzle(session)
适合从 drizzle-orm 迁移,或者你想保留 builder 形状:
select / insert / update / deletedb.query.<resource>findById / findByIriupdateById / updateByIrideleteById / deleteByIri
两者底层是同一个运行时。区别是 API 组织方式,不是存储行为。
快速开始
import { pod, podTable, string, datetime } from '@undefineds.co/drizzle-solid';
const posts = podTable('posts', {
id: string('id').primaryKey(),
title: string('title').predicate('http://schema.org/headline'),
content: string('content').predicate('http://schema.org/text'),
createdAt: datetime('createdAt').predicate('http://schema.org/dateCreated'),
}, {
base: 'https://alice.example/data/posts/',
type: 'http://schema.org/CreativeWork',
});
const client = pod(session);
await client.init(posts);
const created = await client.collection(posts).create({
id: 'post-1.ttl',
title: 'Hello Solid',
content: 'Stored as RDF in a Pod document.',
createdAt: new Date(),
});
if (!created) {
throw new Error('Create failed');
}
const post = client.entity(posts, created['@id']);
console.log(await post.get());
await post.update({ title: 'Updated title' });
await post.delete();Drizzle 风格的精确操作
import { drizzle, podTable, string } from '@undefineds.co/drizzle-solid';
const posts = podTable('posts', {
id: string('id').primaryKey(),
title: string('title').predicate('http://schema.org/headline'),
}, {
base: 'https://alice.example/data/posts/',
type: 'http://schema.org/CreativeWork',
});
const db = drizzle(session);
await db.init(posts);
await db.insert(posts).values({
id: 'post-1.ttl',
title: 'Hello Solid',
});
const row = await db.findById(posts, 'post-1.ttl');
await db.updateById(posts, 'post-1.ttl', {
title: 'Updated title',
});
await db.deleteById(posts, 'post-1.ttl');Pod 布局怎么理解
每个模型不仅描述字段,也描述落点。
base决定文档位置id是 base-relative resource id,例如post-1.ttl或chat-1/messages.ttl#msg-1type是主持久化rdf:type
subjectTemplate 已废弃,只为旧布局或显式兼容保留。新 schema 应该省略它,把精确资源路径放在 id 列里。
旧 subjectTemplate 模式仍兼容:
#{id}:一个文档里多个实体{id}.ttl:一个实体一个文档{id}.ttl#it:一个实体一个文档,并带稳定 fragment{chatId}/messages.ttl#{id}:多变量分区布局
如果旧模板用了多个变量,精确定位就必须提供:
- 完整 IRI,或
- base-relative resource id,例如
chat-1/messages.ttl#msg-1
集合读取 vs 精确实体操作
这是最重要的一条运行时规则。
集合读取
当你要拿一批数据时,用:
client.collection(table).list(...)db.select().from(table)...db.query.<resource>.findMany(...)
精确实体操作
当你要操作一个明确实体时,用:
client.entity(resource, iri)db.query.<resource>.findById(id)db.findById(resource, id)db.findByIri(resource, iri)db.updateById(resource, id, data)db.deleteById(resource, id)db.updateByIri(...)db.deleteByIri(...)
findByLocator / updateByLocator / deleteByLocator 仍临时保留以兼容旧代码,
但已经废弃。精确定位优先使用 base-relative resource id;如果调用方拿到的是
IRI、row、locator 或 id 的混合 target,再用通用 *ByResource helper;已知完整
IRI 时直接用 *ByIri。
不要再把 where({ id: ... }) 或 where(eq(table.id, ...)) 当成精确单体捷径。
SPARQL 支持与后端差异
drizzle-solid 可以跑在不同 Solid 运行时上,但能力有差异。
| 能力 | Community Solid Server | xpod |
| --- | --- | --- |
| 基础 CRUD | ✅ | ✅ |
| 文档通知 | ✅ | ✅ |
| Drizzle 风格读 facade | ✅ | ✅ |
| SPARQL 下推 | ⚠️ 有限 / 经常依赖客户端辅助 | ✅ 更好的进程内支持 |
| 过滤 / 聚合下推 | ❌ 多数走客户端执行 | ✅ 更好的服务端支持 |
| 联邦查询 | ⚠️ 客户端联邦 | ⚠️ 客户端联邦 |
| 进程内本地运行时 | ⚠️ 需要额外启动 | ✅ 通过 @undefineds.co/xpod |
实用规则:
- 有 SPARQL endpoint 或 sidecar 时,集合查询优先走它
- 只有 plain LDP document access 时,精确读写仍然可用
- plain-LDP document mode 不会把精确操作静默扩成扫描
示例
仓库里的标准示例会进入集成验证:
examples/01-quick-start.tsexamples/02-relational-query.tsexamples/03-zero-config-discovery.tsexamples/04-notifications.tsexamples/05-data-discovery.tsexamples/06-federated-query.tsexamples/07-hooks-and-profile.tsexamples/08-iri-based-operations.tsexamples/08-schema-inheritance.tsexamples/09-multi-variable-templates.ts
文档入口
建议从这里开始:
docs/guides/installation.zh-CN.mddocs/api/README.zh-CN.mddocs/guides/migrating-from-drizzle-orm.zh-CN.mddocs/guides/multi-variable-templates.zh-CN.mddocs/guides/notifications.mddocs/guides/data-discovery.md
贡献
推送前运行:
yarn quality
SOLID_ENABLE_REAL_TESTS=true SOLID_SERIAL_TESTS=true yarn vitest --run tests/integration/css示例必须保持可运行且已验证。
License
MIT
相关链接
- GitHub: https://github.com/undefinedsco/drizzle-solid
- npm: https://www.npmjs.com/package/@undefineds.co/drizzle-solid
- xpod: https://github.com/undefinedsco/xpod
