@ rizzle- adapter/ libsql (小雨)
LibSQL适应器用于Drizzle适应器生态系统的实施,支持本地SQLite数据库和Turso.
概览
这个 @drizzle-adapter/libsql 软件包为 Drizzle 适应器接口提供 LibSQL 执行。 虽然你不直接与此软件包互动( 您使用 @drizzle-adapter/core 相反,它为Drizzle适应器生态系统中的LibSQL和Turso提供了支持.
为什么是LibSQL/Turso?
LibSQL和Turso提供了独特的优势:
- 嵌入或无服务器: 使用本地或Turso作为无服务器数据库
- SQLite 兼容性: 建于 SQLite 上, 具有额外特性
- WebSocket 协议: 低纬度的高效二进制协议
- 自动复制: 与 Turso 的内置复制
- 边际计算: 图尔索边缘网络的全球分布
- 地方发展: 以文件为基础的 SQLite 方便本地开发
- 成本效益: 与图尔索进行免费分级和基于使用定价
- 多区域: 与图尔索自动进行多区域部署
完美为:
- 边缘应用程序: 数据来自最近的地点
- 地方发展:嵌入式数据库以促进发展
- 混合部署: 视需要将本地和服务器混合
- 成本敏感项目: 视需要开始免费和规模化
- 全球应用: 用 Turso 自动全局发行
安装
# Install both the core package and the LibSQL adapter
pnpm install @drizzle-adapter/core @drizzle-adapter/libsql
重要:适配器注册
适配器要正确使用 DrizzleAdapterFactory 操作,必须导入它进行自我注册的副作用:
// Import for side effects - adapter will self-register
import '@drizzle-adapter/libsql';
// Now you can use the factory
import { DrizzleAdapterFactory } from '@drizzle-adapter/core';
使用量
配置
import { DrizzleAdapterFactory, TypeDrizzleDatabaseConfig } from '@drizzle-adapter/core';
// Local SQLite database
const localConfig: TypeDrizzleDatabaseConfig = {
DATABASE_DRIVER: 'libsql',
DATABASE_URL: 'file:local.db'
};
// Turso database
const tursoConfig: TypeDrizzleDatabaseConfig = {
DATABASE_DRIVER: 'libsql',
DATABASE_URL: 'libsql://your-database-url.turso.io',
DATABASE_AUTH_TOKEN: 'your-auth-token',
DATABASE_SYNC_URL: 'file:local-replica.db' // Optional sync URL for replica
};
const factory = new DrizzleAdapterFactory();
const adapter = factory.create(config);
Schema 定义
const dataTypes = adapter.getDataTypes();
const users = dataTypes.dbTable('users', {
id: dataTypes.dbInteger('id').primaryKey().autoincrement(),
name: dataTypes.dbText('name').notNull(),
email: dataTypes.dbText('email').notNull().unique(),
metadata: dataTypes.dbText('metadata'), // JSON stored as text
createdAt: dataTypes.dbInteger('created_at')
.default(sql`(strftime('%s', 'now'))`)
});
const posts = dataTypes.dbTable('posts', {
id: dataTypes.dbInteger('id').primaryKey().autoincrement(),
userId: dataTypes.dbInteger('user_id')
.references(() => users.id),
title: dataTypes.dbText('title').notNull(),
content: dataTypes.dbText('content').notNull(),
published: dataTypes.dbInteger('published').default(0),
createdAt: dataTypes.dbInteger('created_at')
.default(sql`(strftime('%s', 'now'))`)
});
基本 CRUD 操作
import { eq, and, or, desc, sql } from 'drizzle-orm';
const client = await adapter.getConnection().getClient();
// INSERT
// Single insert with returning
const [newUser] = await client
.insert(users)
.values({
name: 'John Doe',
email: '[email protected]',
metadata: JSON.stringify({ role: 'user' })
})
.returning();
// Bulk insert
await client
.insert(posts)
.values([
{
userId: newUser.id,
title: 'First Post',
content: 'Hello, world!'
},
{
userId: newUser.id,
title: 'Second Post',
content: 'Another post'
}
]);
// SELECT
// Select all
const allUsers = await client
.select()
.from(users);
// Select with conditions
const user = await client
.select()
.from(users)
.where(eq(users.email, '[email protected]'));
// Select with join
const userPosts = await client
.select({
userName: users.name,
postTitle: posts.title,
content: posts.content,
metadata: users.metadata,
createdAt: sql`datetime(${posts.createdAt}, 'unixepoch')`
})
.from(posts)
.leftJoin(users, eq(posts.userId, users.id))
.where(eq(posts.published, 1))
.orderBy(desc(posts.createdAt));
// UPDATE
await client
.update(users)
.set({
name: 'John Smith',
metadata: JSON.stringify({ role: 'admin' })
})
.where(eq(users.id, newUser.id));
// DELETE
await client
.delete(posts)
.where(
and(
eq(posts.userId, newUser.id),
eq(posts.published, 0)
)
);
全文搜索
// Create FTS table
await client.execute(sql`
CREATE VIRTUAL TABLE posts_fts USING fts5(
title, content,
content='posts',
content_rowid='id'
)
`);
// Search posts
const searchResults = await client
.select({
title: posts.title,
content: posts.content,
author: users.name,
rank: sql`rank`
})
.from(posts)
.leftJoin(users, eq(posts.userId, users.id))
.where(sql`posts.id IN (
SELECT rowid
FROM posts_fts
WHERE posts_fts MATCH ${searchTerm}
ORDER BY rank
)`);
最佳做法
地方发展
// Use file-based SQLite for development
const devAdapter = factory.create({
DATABASE_DRIVER: 'libsql',
DATABASE_URL: 'file:dev.db'
});
与Turso一起生产
// Use Turso for production
const prodAdapter = factory.create({
DATABASE_DRIVER: 'libsql',
DATABASE_URL: process.env.DATABASE_URL,
DATABASE_AUTH_TOKEN: process.env.DATABASE_AUTH_TOKEN
});
复制支持
// Use local replica for better performance
const replicaAdapter = factory.create({
DATABASE_DRIVER: 'libsql',
DATABASE_URL: process.env.DATABASE_URL,
DATABASE_AUTH_TOKEN: process.env.DATABASE_AUTH_TOKEN,
DATABASE_SYNC_URL: 'file:local-replica.db'
});
最佳做法
- 发展流动: 使用基于文件的 SQLite 进行开发
- 生产: 使用Turso进行生产部署
- 复制品:利用当地复制品提高性能
- JSON 处理:将JSON作为TEXT存储,并视需要进行剖析/字符串
- 查询优化: 使用索引和FTS改进性能
捐款
我们欢迎捐款! 请随意提交拉力请求 对于重大变动,请先开出一个问题来讨论你想要改变什么.
相关软件包
- @ 细雨适应器/ 核心 - 核心接口和类型
- @ 细雨适应器/ sqlite- core - 共享 SQLite 功能