Appwrite

BaaSオープンソースセルフホストプライバシーリアルタイム認証

BaaSプラットフォーム

Appwrite

概要

Appwriteは、プライバシーとセキュリティを重視したオープンソースのBaaSプラットフォームです。セルフホスト可能でありながら、クラウド版も提供しており、開発者が完全にコントロールできる環境を実現します。データベース、認証、ストレージ、クラウド関数などの包括的なバックエンドサービスを統一されたAPIで提供し、モダンなアプリ開発を支援します。

詳細

Appwriteは、プライバシーファーストの設計思想のもと、開発者が自分のインフラで完全にコントロールできるBaaS環境を提供します。Docker Composeによる簡単なセットアップから本格的なKubernetes展開まで対応し、データの主権を重視する企業や開発者から高い評価を得ています。

リアルタイムデータベース、多様な認証プロバイダー、ファイルストレージ、クラウド関数、プッシュ通知など、現代的なアプリケーションに必要な機能を包括的に提供。Web、モバイル、デスクトップ、サーバーサイドまで幅広いプラットフォームに対応したSDKを備えています。

メリット・デメリット

メリット

  • オープンソース: ソースコードが公開されており、透明性とカスタマイズ性が高い
  • セルフホスト対応: 自社サーバーでの運用により、データの完全なコントロールが可能
  • プライバシー重視: GDPR準拠やデータローカライゼーションに対応
  • 包括的な機能: 認証、データベース、ストレージ、関数などオールインワン
  • 豊富なSDK: 多様なプログラミング言語とプラットフォームに対応

デメリット

  • セルフホストの運用負荷: インフラ管理とメンテナンスが必要
  • 学習コストの存在: 独自のAPIとアーキテクチャに慣れる必要がある
  • コミュニティベース: 商用サポートが限定的
  • スケーリングの複雑さ: 大規模運用時の最適化には専門知識が必要

参考ページ

コード例

1. 基本的なクライアント初期化と認証

import { Client, Account } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const account = new Account(client);

// ユーザー登録
const user = await account.create(
    'unique-user-id',
    '[email protected]',
    'secure-password',
    '山田太郎'
);
console.log(user);

// ログイン
const session = await account.createEmailPasswordSession(
    '[email protected]',
    'secure-password'
);
console.log(session);

2. データベース操作(CRUD)

import { Client, Databases } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const databases = new Databases(client);

// ドキュメント作成
const document = await databases.createDocument(
    'database-id',
    'posts-collection-id',
    'unique-document-id',
    {
        title: 'Appwriteの使い方',
        content: 'Appwriteを使った開発の基本...',
        author: 'user-id',
        publishedAt: new Date().toISOString()
    }
);

// ドキュメント取得
const post = await databases.getDocument(
    'database-id',
    'posts-collection-id',
    'document-id'
);

// ドキュメント一覧取得
const posts = await databases.listDocuments(
    'database-id',
    'posts-collection-id',
    [Query.equal('status', 'published')]
);

3. ファイルストレージ操作

import { Client, Storage } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const storage = new Storage(client);

// ファイルアップロード
const file = await storage.createFile(
    'bucket-id',
    'unique-file-id',
    document.getElementById('file-input').files[0]
);

// ファイル一覧取得
const files = await storage.listFiles('bucket-id');

// ファイルダウンロードURL取得
const downloadUrl = storage.getFileDownload('bucket-id', 'file-id');

// ファイルプレビューURL取得
const previewUrl = storage.getFilePreview(
    'bucket-id',
    'file-id',
    400, // width
    300, // height
    'center', // gravity
    80 // quality
);

4. リアルタイム機能

import { Client, Databases } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const databases = new Databases(client);

// リアルタイム購読
const unsubscribe = client.subscribe(
    ['databases.database-id.collections.messages.documents'],
    response => {
        console.log('新しいメッセージ:', response);
        // UIを更新
        updateMessageList(response.payload);
    }
);

// 購読解除
// unsubscribe();

5. クラウド関数の実行

import { Client, Functions } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const functions = new Functions(client);

// 関数実行
const execution = await functions.createExecution(
    'function-id',
    JSON.stringify({
        operation: 'sendWelcomeEmail',
        userId: 'user-id',
        language: 'ja'
    })
);

console.log(execution.response);

6. React.jsアプリケーション統合例

import React, { useState, useEffect } from 'react';
import { Client, Account, Databases } from 'appwrite';

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('your-project-id');

const account = new Account(client);
const databases = new Databases(client);

function App() {
    const [user, setUser] = useState(null);
    const [posts, setPosts] = useState([]);

    useEffect(() => {
        // ユーザー情報取得
        account.get()
            .then(setUser)
            .catch(() => setUser(null));

        // 投稿一覧取得
        if (user) {
            databases.listDocuments('database-id', 'posts-collection-id')
                .then(response => setPosts(response.documents));
        }
    }, [user]);

    const login = async (email, password) => {
        try {
            await account.createEmailPasswordSession(email, password);
            const userData = await account.get();
            setUser(userData);
        } catch (error) {
            console.error('ログインエラー:', error);
        }
    };

    const logout = async () => {
        try {
            await account.deleteSession('current');
            setUser(null);
            setPosts([]);
        } catch (error) {
            console.error('ログアウトエラー:', error);
        }
    };

    return (
        <div>
            {user ? (
                <div>
                    <h1>こんにちは、{user.name}さん</h1>
                    <button onClick={logout}>ログアウト</button>
                    <div>
                        {posts.map(post => (
                            <div key={post.$id}>
                                <h3>{post.title}</h3>
                                <p>{post.content}</p>
                            </div>
                        ))}
                    </div>
                </div>
            ) : (
                <LoginForm onLogin={login} />
            )}
        </div>
    );
}