@mapyojojo/vision-shelf-sdk
v0.1.0
Published
Supabase authentication and data synchronization SDK
Readme
@vision-shelf/sdk (Vision Shelf 共通SDKパッケージ)
@vision-shelf/sdk は、認証(Supabase Auth)、データベース接続・リアルタイム同期購読、AI(Gemini API)マルチモーダル画像解析ロジックをカプセル化した、ポータブルな共通パッケージ(SDK)です。
接続情報だけでなく、画像解析エンジン(LLM)自体も「Gemini(デフォルト)」と「ローカルLLM(Ollama等)」を動的に注入(Inject)可能な設計へと進化しました。これにより、セキュリティ要件の厳しい社内LANやオンプレミス環境など、異なるインフラ環境へ同一のコア機能を持ったアプリケーションを爆速かつ柔軟に展開することが可能です。
🚀 導入方法
新しいアプリケーション(例: apps/office-supplies)から本SDKを利用するには、以下の手順でモノレポに追加します。
1. package.json への追加
依存関係に @vision-shelf/sdk を追加します。
{
"dependencies": {
"@vision-shelf/sdk": "*"
}
}2. ローカルリンクの確立
モノレポのルートで以下を実行し、依存パッケージを解決します。
npm install🛠 モジュール構成とAPIリファレンス
本SDKは Next.js などの React Server Components (RSC) 環境での不要な React APIs 混入を防ぐため、サブパスエクスポートを導入しています。
1. @vision-shelf/sdk (Core / サーバーコンテキスト向け)
サーバーアクション、サーバーコンポーネント、ミドルウェアなど非ブラウザ環境(およびReact依存のないモジュール)向けのエントリポイントです。
サーバーSDKの初期化
import { createServerSdk, OllamaAnalyzer } from "@vision-shelf/sdk";
// パターンA: 従来通りGemini APIを使用する場合(下位互換性)
const sdk = createServerSdk(
{
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
geminiApiKey: process.env.GEMINI_API_KEY!,
},
{
// Cookieの取得・設定方法を注入 (Next.js 等の環境に準拠)
getAll() {
return myCookieStore.getAll();
},
setAll(cookies) {
cookies.forEach((c) => myCookieStore.set(c.name, c.value, c.options));
},
},
);
// パターンB: 完全にセキュアなローカルLLM(Ollama)を使用する場合
const sdk = createServerSdk(
{
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
// Geminiのキーは不要!
aiAnalyzer: new OllamaAnalyzer("http://localhost:11434"),
},
{
// Cookieの取得・設定方法を注入 (Next.js 等の環境に準拠)
getAll() {
return myCookieStore.getAll();
},
setAll(cookies) {
cookies.forEach((c) => myCookieStore.set(c.name, c.value, c.options));
},
},
);提供サービス
sdk.auth(ServerAuthService):getUser(): セッションユーザーの検証・取得。signIn(email, password): パスワードを用いたサインイン処理。sendPasswordResetEmail(email, redirectTo): パスワードリセット用URLリンクを送信。updateUserPassword(newPassword): ログイン中のユーザーのパスワード変更。
sdk.db(DatabaseService):list<T>(table, options?): テーブルの全件取得(orderColumn・ascendingオプション対応)。insert(table, data): 単一レコードの追加。update(table, id, data): ID指定によるレコードの更新。delete(table, id): ID指定によるレコードの削除。
sdk.ai(ImageAnalyzer):analyzeImages<T>({ images, prompt }): 複数の画像とテキストプロンプトを、注入されたAI解析エンジン(GeminiまたはOllama等)に安全に投げて、ジェネリクスTで指定した任意のJSONスキーマオブジェクトとして結果を取得・パース。
2. @vision-shelf/sdk/react (Client / React専用エントリ)
"use client" ディレクティブ下(ブラウザ環境)で React Hook や Client SDK インスタンスを利用するためのエントリポイントです。
クライアントSDKの初期化
import { createClientSdk } from "@vision-shelf/sdk";
export const sdk = createClientSdk({
supabaseUrl: "https://your-project.supabase.co",
supabaseAnonKey: "your-anon-key",
});提供サービス (Client SDK)
sdk.auth(ClientAuthService):getUser(): セッションユーザーの検証・取得。signIn(email, password): パスワードを用いたサインイン処理。signOut(): サインアウト処理。updateUserPassword(newPassword): ログイン中のユーザーのパスワード変更。
sdk.db(DatabaseService): サーバー側と同じlist / insert / update / deleteAPI。
提供Hook
useShelfItems<T, DbT>({ sdk, table, mapDbToModel, orderColumn?, ascending? }):- 引数:
sdk: 初期化済みのVisionShelfClientSdkインスタンス。table: 同期対象のSupabaseテーブル名(例:"seasonings")。mapDbToModel: データベースのオブジェクト構造をアプリケーション用のモデル構造にマッピングする関数。orderColumn: ソートカラム名(デフォルト:"created_at")。ascending: 昇順ソートかどうか(デフォルト:false)。
- 戻り値:
items: 同期済みのモデル配列(T[])。isLoaded: 初期ロードが完了したかどうかのフラグ(boolean)。refetch: 明示的に手動再取得を行うための非同期関数。
- 機能:
- コンポーネントのマウント時に初期データを取得。
- 同時に Postgres Changes を用いたRealtime購読チャンネルを開設し、他端末でのデータ登録・変更・削除を瞬時に受信して一覧データを自動同期します。アンマウント時には自動的にチャンネルをクリーンアップします。
- 引数:
🤖 マルチAIエンジン(Adapterパターン)
本SDKの画像解析機能(sdk.ai)は、Adapterパターンを採用してインターフェースで抽象化されています。これにより、外部接続を制限したい社内ネットワーク環境(オンプレミス)であっても、ローカルLLM(Ollama等)へ容易に差し替えて運用することが可能です。
インターフェース定義 (ImageAnalyzer)
画像解析を行うすべてのエンジンは、以下の ImageAnalyzer インターフェースを実装しています。
import { z } from "zod";
export interface AnalyzeOptions<T = any> {
images: (File | ImageInput)[];
prompt: string;
modelName?: string;
schema?: z.ZodType<T, any, any>; // 🔒 データ構造検証用のZodスキーマ (任意)
}
export interface ImageAnalyzer {
analyzeImages<T>(options: AnalyzeOptions<T>): Promise<{
data?: T;
error?: string;
rawResponse?: string;
}>;
}提供されているAdapterクラスと利用方法
1. GeminiAnalyzer (クラウドAPIモデル)
Google Gemini APIを使用した、クラウドベースの高性能マルチモーダル解析を提供します(初期化方法および必要な環境変数については、上部の【サーバーSDKの初期化(パターンA)】および最下部の環境変数一覧を参照してください)。
2. OllamaAnalyzer (ローカルLLM/オンプレミスモデル)
ローカル環境やオンプレミス環境で起動している Ollama API と通信し、外部ネットワークと隔離された完全セキュアな画像解析を実現します(接続方法、初期化方法、および必要な環境変数については、上部の【サーバーSDKの初期化(パターンB)】および最下部の環境変数一覧を参照してください)。
🔒 セキュリティ機能と対策
1. ZodによるAI解析データのスキーマ検証
AIから返却されたデータが、アプリケーション側の予期するデータ構造(例:ガンプラ棚用の KitData[] や調味料棚用の SeasoningData[])に合致しているかを、パース直後に zod スキーマを用いて強制検証します。
AIが崩れたJSONを出力したり、プロンプトインジェクション等により意図しないオブジェクト構造が返却された場合でも、安全に検知してエラー { error: "AI解析データのスキーマ検証に失敗しました。" } を返却し、アプリケーション側のクラッシュを防ぎます。
- 利用例 (スキーマ検証の有効化):
import { z } from "zod"; // スキーマ定義 const itemSchema = z.object({ name: z.string().nullable(), quantity: z.number(), }); const itemListSchema = z.array(itemSchema); // 解析実行 (schemaオプションを渡す) const result = await sdk.ai.analyzeImages({ images: [imageFile], prompt: "画像を解析してアイテム一覧をJSONで返して", schema: itemListSchema, // 🔒 ここでスキーマを指定! }); if (result.error) { console.error(result.error); // スキーマ検証に失敗した場合はエラーが返る } else { console.log(result.data); // 型安全に検証された配列 }
2. SSRF (Server-Side Request Forgery) の防御とバイパススイッチ
ローカルLLMへの切り替えに対応する OllamaAnalyzer では、エンドポイントへの不正なリクエスト送信による SSRF 脆弱性を緩和するための検知ロジックを実装しています。
SSRF防御仕様: 本番環境 (
process.env.NODE_ENV === "production") の場合、OllamaAnalyzerの接続先にローカルホスト(localhost、127.0.0.1、[::1])やリンクローカルアドレス(169.254.169.254)、その他プライベートIP空間(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)が指定された場合、SSRFの危険性があるとみなして接続を自動的に遮断(コンストラクタで例外スロー)します。ALLOW_PRIVATE_NETWORKS バイパススイッチ (オンプレ回避策): 将来的に本アプリを社内オンプレミスや閉域網などで動作させ、本番環境でもプライベートIP上の Ollama に接続したい場合は、環境変数
ALLOW_PRIVATE_NETWORKS=trueを設定することで、コードを1ミリも書き換えることなく検知ロジックをバイパスし通信を許可することができます。環境変数一覧: | 環境変数 | 設定値 | 説明 | | :------------------------------ | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------ | |
NEXT_PUBLIC_SUPABASE_URL| URL文字列 | SupabaseプロジェクトのAPI URL(SDKの共通基盤として必須) | |NEXT_PUBLIC_SUPABASE_ANON_KEY| JWT文字列 | Supabaseのクライアント用匿名キー(RLSが強制される安全なキー、SDKの共通基盤として必須) | |GEMINI_API_KEY| APIキー文字列 | Gemini APIを利用してクラウドベースの画像解析を行う場合に必須(パターンA用) | |ALLOW_PRIVATE_NETWORKS|true| 本番環境(Vercel等)でローカル・プライベートIPへのSSRFチェックを例外的にバイパスし、オンプレミスでのOllama等の利用を許可するフラグ(パターンB用) |
