在 Next.js 中使用 Drizzle ORM 和 Bun 配置 Turso 数据库

786 阅读3分钟

原文链接:www.shenlu.me/blog/use-tu…

2024年4月8日,PlanetScale 免费 Hobby 数据库计划将不再可用,因此我开始寻找替代方案。在对市场上其他无服务器数据库进行比较后,我决定选择 Turso 作为 Amazing Endemic Species 项目的数据库。

aes-showcase.png

此外,我去年在 Next.js 项目中使用了 Prisma 作为对象关系映射(ORM)工具,但我不喜欢它独特的 API 设计语法和抽象级别。直到我发现了 Drizzle ORM,它的理念是"If you know SQL, you know Drizzle ORM",它提供了从 SQL 到高层抽象的过渡,并且可以用于读取嵌套关系。

在本文中,我将介绍如何在 Next.js 中使用 TursoDrizzle ORM

前提条件

  • Bun v1.1+

安装 Drizzle ORM 和 Drizzle kit

你应该已经安装了 Drizzle ORMDrizzle kit。可以通过运行以下命令来安装:

bun add drizzle-orm @libsql/client
bun add -D drizzle-kit

设置 Turso

安装 Turso CLI

Turso CLI 将帮助你管理数据库,在其他区域创建副本,并连接到数据库 shell。你可以通过以下命令安装它:

curl -sSfL https://get.tur.so/install.sh | bash

然后检查Turso CLI的版本。

turso -v
turso version v0.93.8

注册或登录 Turso

turso auth signup
turso auth login
# Already signed in as shenlu89. Use turso auth logout to log out of this account

创建 Turso 数据库

使用以下命令创建一个名为 aes 的数据库:

turso db create aes
# Created database aes at group default in 1.758s.
# Start an interactive SQL shell with:
# turso db shell aes
# To see information about the database, including a connection URL, run:
# turso db show aes
# To get an authentication token for the database, run:
# turso db tokens create aes

使用以下命令显示 aes 数据库的信息:

turso db show aes
# Name: aes
# URL: libsql://aes-*****.turso.io
# ID: ********
# Group: default
# Version: 0.24.7
# Locations: sin, sjc
# Size: 4.1 kB
# Sleeping: No
# Bytes Synced: 0 B
# Is Schema: No
# Database Instances:
# NAME TYPE LOCATION
# sjc primary sjc
# sin replica sin

使用以下命令连接到数据库:

turso db shell aes
# Connected to aes at libsql://aes-****.turso.io
# Welcome to Turso SQL shell!
# Type ".quit" to exit the shell and ".help" to list all available commands.
# →

设置Turso数据库

Turso是一个基于libSQL的SQLite兼容数据库,它是SQLite的开放贡献分支。为开发过程设置本地数据库非常简单。

创建db文件夹以连接Turso数据库

tree -L 3 --gitignore db
# db
# ├── index.ts
# ├── libsql
# │   └── aes.db
# ├── schema.ts
# └── seed.ts

更新环境变量

在根目录下创建 .env 文件,并从以下命令中获取连接URL和认证令牌:

turso db show --url aes
#libsql://aes-*****.turso.io
turso db tokens create aes
#eyj******Cw

然后将连接URL和认证令牌粘贴到 .env 中,如下所示:

TURSO_DATABASE_URL='libsql://aes-*****.turso.io'
TURSO_AUTH_TOKEN="*******"

设置 Drizzle 配置文件

在项目根目录下创建一个 drizzle.config.ts 文件,并添加以下内容:

import type { Config } from "drizzle-kit";
export default {
  dialect: "sqlite",
  schema: "./db/schema.ts",
  out: "./db/migrations",
  driver: "turso",
  dbCredentials: {
    url: process.env.TURSO_DATABASE_URL!,
    authToken: process.env.TURSO_AUTH_TOKEN!,
  },
} satisfies Config;

将 Drizzle ORM 连接到 Turso

要连接 Turso 数据库,我在 db/index.ts 中编写了以下代码:

import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
const client = createClient({
  url: process.env.TURSO_CONNECTION_URL!,
  authToken: process.env.TURSO_AUTH_TOKEN!,
});
export const db = drizzle(client);

在 Turso 数据库中创建表

以下代码展示了如何在aes数据库中创建一个 aes 表:

import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const aes = sqliteTable("aes", {
  id: integer("id").notNull().primaryKey().unique(),
  createAt: text("createAt")
    .notNull()
    .default(sql`(current_timestamp)`),
});

生成迁移

根据你的 Drizzle 模式生成迁移。

bunx drizzle-kit generate
# drizzle-kit: v0.22.4
# drizzle-orm: v0.31.1
# No config path provided, using default 'drizzle.config.ts'
# Reading config file '/home/a/aes/drizzle.config.ts'
# 1 tables
# aes 2 columns 1 indexes 0 fks

这将生成一个迁移 SQL 文件:

CREATE TABLE `aes` (
`id` integer PRIMARY KEY NOT NULL,
`createAt` text DEFAULT (current_timestamp) NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `aes_id_unique` ON `aes` (`id`);

将模式推送到Turso数据库

使用 drizzle-kit push 命令可以将模式更改直接推送到aes数据库:

bunx drizzle-kit push
# drizzle-kit: v0.22.4
# drizzle-orm: v0.31.1
# No config path provided, using default path
# Reading config file '/home/a/aes/drizzle.config.ts'
# [✓] Pulling schema from database…[✓] Changes applied

之后,你将在Turso数据库中看到aes表的模式。

turso db shell aes '.schema'
# CREATE TABLE `aes` (
# `id` integer PRIMARY KEY NOT NULL,
# `createAt` text DEFAULT (current_timestamp) NOT NULL
# );
# CREATE UNIQUE INDEX `aes_id_unique` ON `aes` (`id`);

今天就先到这里,之后将继续添加更多内容。

源码:github.com/shenlu89/am…