0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tursoを軽く触ってみた

Last updated at Posted at 2025-03-31

はじめに

Tursoを触ってみたので、Next.jsでTursoからデータ取得ができるまでのやり方を書いていきます。

ドキュメント等

Tursoとはなんぞや

Tursoは軽量で高速なSQLiteデータベースをベースにしたクラウドデータベースサービスです。
以下はTursoの主な特徴です:

アーキテクチャと特徴

  • SQLiteベース:SQLiteの安定性と互換性を受け継いでいます
  • libSQL:TursoはlibSQL(SQLiteのフォーク)を使用して拡張機能を提供
  • エッジデプロイメント:グローバルなエッジロケーションにデータを配置できます

パフォーマンスと設計について

  • 高速:低レイテンシで動作するように設計されています
  • 小型:リソース消費が少なく、軽量です
  • 組み込みレプリケーション機能

UXについて

  • CLIツールを提供

  • 複数の言語のSDKをサポート

Tursoでデータベース作成

Tursoを使用するにはアカウントを作成する必要があります。
以下から作成をしてください。

Turso CLIをインストール

Turso CLIをインストールしておくと便利なので、インストールしておきます。
以下のドキュメントの手順に沿ってインストールできます。(Turso CLIを使わなくてもデータベースなどの作成などはできます。)

Macの場合は、以下のコマンドでインストールできます。

brew install tursodatabase/tap/turso

以下のコマンドで、Tursoにログインできます。

turso auth signup

データベース、テーブル作成手順

①以下のコマンドでテーブルを作成します。

turso db create test

②作成されているかを確認
以下のURLを開き、右上の「Login」を開くと、自分のダッシュボード画面に遷移するので、「Database」タブを開いて「test」が作成されているかを確認します。

以下のように作成されているはず

スクリーンショット 2025-03-31 17.01.29.png

③テーブルを作成

  • 「test」を開き、「Outerbase Studio」を開きます。
    スクリーンショット 2025-03-31 17.02.36.png

    スクリーンショット 2025-03-31 17.06.56.png

  • 「New+」をクリックし、以下のようにテーブルの情報を設定し、「Save」をクリックすると、テーブルが作成されます。
    スクリーンショット 2025-03-31 17.07.59.png
    ↓「Save」をクリック
    スクリーンショット 2025-03-31 17.09.54.png

④データを追加
以下のようにデータを追加します。
スクリーンショット 2025-03-31 17.11.01.png

これでテーブルの準備は完了です。

Next.jsアプリケーションからTursoにアクセスしてみよう

Tursoのデータベースにアクセスするには、トークンの作成とアクセスしたいデータベースのURLを取得する必要があります。

トークンの作成、取得

まずは、CLIで以下のコマンドを実行しましょう。

turso db tokens create test

実行後、トークンが作成され、ターミナルに出力されるので、コピーしておきましょう。

URLを取得

URLは以下からコピーできます。
スクリーンショット 2025-03-31 17.16.17.png

Next.jsアプリケーションから呼び出してみよう

以下のコードを作成します。

.env.local
TURSO_DATABASE_URL="取得したURL"
TURSO_AUTH_TOKEN="取得したトークン"
/lib/db.ts
import { createClient } from "@libsql/client";

const url = process.env.TURSO_DATABASE_URL;
const authToken = process.env.TURSO_AUTH_TOKEN;

if (!url || !authToken) {
  throw new Error('TURSO_DATABASE_URL and TURSO_AUTH_TOKEN must be set');
}

export const turso = createClient({
  url,
  authToken,
});
/api/item/route.ts
import { createClient } from "@libsql/client";

const client = createClient({
  url: process.env.TURSO_DATABASE_URL || "libsql://test.turso.io",
  authToken: process.env.TURSO_AUTH_TOKEN,
});

async function initializeDb() {
  try {
    await client.execute(`
      CREATE TABLE IF NOT EXISTS items (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL
      )
    `);
  } catch (error) {
    console.error("Error initializing database:", error);
  }
}

initializeDb();

export async function GET() {
  try {
    const result = await client.execute("SELECT * FROM items ORDER BY id DESC");
    return Response.json(result.rows);
  } catch (error) {
    console.error("Error fetching items:", error);
    return Response.json({ error: "Failed to fetch items" }, { status: 500 });
  }
}

export async function POST(request: Request) {
  try {
    const { name } = await request.json();

    if (!name || typeof name !== "string") {
      return Response.json({ error: "Name is required" }, { status: 400 });
    }

    await client.execute({
      sql: "INSERT INTO items (name) VALUES (?)",
      args: [name],
    });

    return Response.json({ success: true });
  } catch (error) {
    console.error("Error adding item:", error);
    return Response.json({ error: "Failed to add item" }, { status: 500 });
  }
}

export async function DELETE(request: Request) {
  try {
    const { searchParams } = new URL(request.url);
    const id = searchParams.get("id");

    if (!id) {
      return Response.json({ error: "ID is required" }, { status: 400 });
    }

    await client.execute({
      sql: "DELETE FROM items WHERE id = ?",
      args: [id],
    });

    return Response.json({ success: true });
  } catch (error) {
    console.error("Error deleting item:", error);
    return Response.json({ error: "Failed to delete item" }, { status: 500 });
  }
}

page.tsx
import { turso } from "@/lib/db";

export default async function Home() {
  const db = await turso.execute("SELECT * FROM users");
  const users = db.rows;

  return (
    <div className="grid grid-rows-[auto_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-8 sm:p-20 font-[family-name:var(--font-geist-sans)]">
      <h1 className="text-2xl font-bold">Turso Demo App</h1>

      <div className="w-full max-w-4xl">
        <h2 className="text-xl mb-4">ユーザー一覧</h2>

        {users.length > 0 ? (
          <div className="overflow-x-auto">
            <table className="min-w-full bg-white border border-gray-200">
              <thead className="bg-gray-100">
                <tr>
                  {Object.keys(users[0]).map((key) => (
                    <th key={key} className="px-4 py-2 text-left border-b">
                      {key}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {users.map((user, index) => (
                  <tr
                    key={index}
                    className={index % 2 === 0 ? "bg-gray-50" : "bg-white"}
                  >
                    {Object.values(user).map((value, valueIndex) => (
                      <td key={valueIndex} className="px-4 py-2 border-b">
                        {value !== null ? String(value) : "NULL"}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <p>ユーザーデータがありません</p>
        )}
      </div>

      <p className="text-sm text-gray-500">© 2025 Turso Demo</p>
    </div>
  );
}

以下のようにデータを取得できました!
スクリーンショット 2025-03-31 17.31.49.png

最後に

他にも色々な記事を書いているので、よければ読んでいってください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?