npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mapyojojo/vision-shelf-sdk

v0.2.0

Published

Supabase authentication and data synchronization SDK

Readme

@mapyojojo/vision-shelf-sdk (Vision Shelf 共通SDKパッケージ)

@mapyojojo/vision-shelf-sdk は、認証(Supabase Auth)、データベース接続・リアルタイム同期購読、AI(Gemini API)マルチモーダル画像解析ロジックをカプセル化した、ポータブルな共通パッケージ(SDK)です。

接続情報に加え、画像解析エンジンとして Gemini(デフォルト)や Ollama などを注入できます。アプリケーションのコア機能を維持しながら、クラウド、社内LAN、オンプレミスなどの環境に応じて解析先を選択できます。


🚀 導入方法

新しいアプリケーション(例: apps/office-supplies)から本SDKを利用するには、以下の手順でモノレポに追加します。

1. package.json への追加

依存関係に @mapyojojo/vision-shelf-sdk を追加します。

{
  "dependencies": {
    "@mapyojojo/vision-shelf-sdk": "^0.2.0"
  }
}

2. ローカルリンクの確立

モノレポのルートで以下を実行し、依存パッケージを解決します。

npm install

React 19 は利用アプリ側でインストールしてください。SDKのHookとコンポーネントはアプリと同じReactインスタンスを使用するため、Reactはpeer dependencyです。


🛠 モジュール構成とAPIリファレンス

本SDKは Next.js などの React Server Components (RSC) 環境での不要な React APIs 混入を防ぐため、サブパスエクスポートを導入しています。

1. @mapyojojo/vision-shelf-sdk (Core / サーバーコンテキスト向け)

サーバーアクション、サーバーコンポーネント、ミドルウェアなど非ブラウザ環境(およびReact依存のないモジュール)向けのエントリポイントです。

サーバーSDKの初期化

import { createServerSdk, OllamaAnalyzer } from "@mapyojojo/vision-shelf-sdk";

// パターンA: 従来通りGemini APIを使用する場合(下位互換性)
const geminiSdk = 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, headers) {
      cookies.forEach((c) => myCookieStore.set(c.name, c.value, c.options));
      // proxy等ではSupabaseが渡すcache-control等のheadersもレスポンスへ転送する
    },
  },
);

// パターンB: ローカルまたはオンプレミスの Ollama を使用する場合
const ollamaSdk = createServerSdk(
  {
    supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
    supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    // Ollama 利用時は Gemini の API キーは不要
    aiAnalyzer: new OllamaAnalyzer("http://localhost:11434"),
  },
  {
    // Cookieの取得・設定方法を注入 (Next.js 等の環境に準拠)
    getAll() {
      return myCookieStore.getAll();
    },
    setAll(cookies, headers) {
      cookies.forEach((c) => myCookieStore.set(c.name, c.value, c.options));
      // proxy等ではSupabaseが渡すcache-control等のheadersもレスポンスへ転送する
    },
  },
);

提供サービス

  • sdk.auth (ServerAuthService):
    • getUser(): セッションユーザーの検証・取得。
    • signIn(email, password): パスワードを用いたサインイン処理。
    • sendPasswordResetEmail(email, redirectTo): パスワードリセット用URLリンクを送信。
    • updateUserPassword(newPassword): ログイン中のユーザーのパスワード変更。
  • sdk.db (DatabaseService):
    • list<T>(table, options?): orderColumn・ascending・filterColumn・filterValue を指定して取得。
    • insert(table, data): 単一または複数レコードの追加。
    • update(table, id, data): ID指定によるレコードの更新。
    • delete(table, id): ID指定によるレコードの削除。data に削除したIDの配列を返すため、0件だった場合も判定可能。削除行を返すには対象行の SELECT 権限と RLS による可視性も必要です。
  • sdk.ai (ImageAnalyzer):
    • analyzeImages<T>({ images, prompt, schema? }): 複数の画像とテキストプロンプトを、注入されたAI解析エンジン(GeminiまたはOllama等)へ送信し、JSONをパースして結果を返します。schema を指定した場合は safeParse で検証します。

2. @mapyojojo/vision-shelf-sdk/react (Client / React専用エントリ)

"use client" ディレクティブ下(ブラウザ環境)で React Hook やコンポーネントを利用するためのエントリポイントです。createClientSdk はルートの @mapyojojo/vision-shelf-sdk から、useShelfItems などの Hook と SplashScreen などの React 向け API は @mapyojojo/vision-shelf-sdk/react から import してください。

クライアントSDKの初期化

import { createClientSdk } from "@mapyojojo/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 / delete API。

提供Hook

  • useShelfItems<T, DbT>({ sdk, table, mapDbToModel, orderColumn?, ascending?, filterColumn?, filterValue?, enabled? }):
    • 引数:
      • sdk: 初期化済みの VisionShelfClientSdk インスタンス。
      • table: 同期対象のSupabaseテーブル名(例: "seasonings")。
      • mapDbToModel: データベースのオブジェクト構造をアプリケーション用のモデル構造にマッピングする関数。
      • orderColumn: ソートカラム名(デフォルト: "created_at")。
      • ascending: 昇順ソートかどうか(デフォルト: false)。
      • filterColumn と filterValue: 指定すると、その列の値で取得・Realtime購読を絞り込む。
      • enabled: false の間は取得・購読を行わない(デフォルト: true)。
    • 戻り値:
      • items: 同期済みのモデル配列(T[])。
      • isLoaded: 初期ロードが完了したかどうかのフラグ(boolean)。
      • refetch: 明示的に手動再取得を行うための非同期関数。
      • error: 取得に失敗した場合のメッセージ。refetch は失敗をthrowせず、この値を更新します。
    • 機能:
      • コンポーネントのマウント時に初期データを取得。
      • 同時に Postgres Changes を用いたRealtime購読チャンネルを開設し、他端末でのデータ登録・変更・削除を瞬時に受信して一覧データを自動同期します。アンマウント時には自動的にチャンネルをクリーンアップします。
      • 棚の切り替え後に以前の棚の遅い応答が到着しても、表示を上書きしません。

その他のReact向けAPI

  • compressImage(file, { maxSize?, quality? }): ブラウザの画像をJPEGへ圧縮し、処理できない場合は元ファイルを返します。
  • useForgotPassword(sendEmail)、useResetCallback(router)、useUpdatePassword(updatePassword, router): パスワード再設定フロー用の共通Hookです。Next.jsのrouterやアプリ固有の送信処理は呼び出し側から渡します。
  • SplashScreen: isLoaded が必須で、appName・subtitle・iconSrc・accentColor を指定できます。

Tailwind CSS v4を利用するアプリでは、SDKのクラスもスキャン対象に追加してください。@source のパスは利用アプリのCSSファイルからの相対パスです。たとえばルート直下の app/globals.css なら次のようにします。

@import "tailwindcss";
@source "../node_modules/@mapyojojo/vision-shelf-sdk/dist/react/**/*.{js}";

accentColor に渡すクラスがアプリ側にもSDK側にも静的な文字列として存在しない場合は、アプリ側のCSSで、たとえば @source inline("bg-indigo-600") のように指定してください。


🤖 マルチAIエンジン(Adapterパターン)

本SDKの画像解析機能(sdk.ai)は、Adapterパターンを採用してインターフェースで抽象化されています。これにより、ローカルまたはオンプレミス環境の Ollama などへ解析先を切り替えられます。その場合、画像を外部AIサービスへ送信せずに解析できます。

インターフェース定義 (ImageAnalyzer)

画像解析を行うすべてのエンジンは、以下の ImageAnalyzer インターフェースを実装しています。

import type { ImageInput } from "@mapyojojo/vision-shelf-sdk";

export interface AnalyzeOptions<T = unknown> {
  images: (File | ImageInput)[];
  prompt: string;
  modelName?: string;
  schema?: {
    safeParse: (data: unknown) => { success: boolean; data?: T; error?: unknown };
  }; // データ構造検証用のスキーマ (任意)
}

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 と通信し、画像を外部AIサービスへ送信せずに解析できます。通信経路や Ollama の運用環境の安全性は、利用側で確認してください(初期化方法と環境変数は、上部の「サーバーSDKの初期化(パターンB)」および下部の環境変数一覧を参照)。


🔒 セキュリティ機能と対策

1. safeParse互換スキーマによるAI解析データの検証

schema オプションに safeParse(data: unknown) 互換のスキーマを渡すと、JSONパース後のAI解析データがアプリケーション側の予期する構造(例:KitData[] や SeasoningData[])に合致するか検証します。Zodは利用できるスキーマの一例であり、SDKのインターフェースはZod固有ではありません。schema を省略した場合、構造の検証は行いません。

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, // safeParse 互換スキーマを指定
    });
    
    if (result.error) {
      console.error(result.error); // スキーマ検証に失敗した場合はエラーが返る
    } else {
      console.log(result.data); // 型安全に検証された配列
    }

2. SSRF (Server-Side Request Forgery) リスクの緩和と例外設定

ローカルLLMへの切り替えに対応する OllamaAnalyzer では、エンドポイントへの不正なリクエスト送信による SSRF 脆弱性を緩和するための検知ロジックを実装しています。

  • 接続先アドレスの制限: 本番環境(process.env.NODE_ENV === "production")では、OllamaAnalyzer の接続先ホスト名が localhost、IPv4ループバック(127.0.0.0/8)、IPv6ループバック(::1)、IPv4リンクローカル(169.254.0.0/16)、プライベートIPv4(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)、または fc00:・fd00:・fe80: で始まるIPv6アドレスに該当すると、コンストラクタで例外を投げます。これは接続先URLのホスト名に対するチェックであり、SSRFリスクを完全に排除するものではありません。

  • ALLOW_PRIVATE_NETWORKS による例外設定: 本番環境で社内ネットワーク上の Ollama に接続する場合は、環境変数 ALLOW_PRIVATE_NETWORKS=true を設定すると、上記の接続先アドレス制限を解除できます。この設定はSSRFリスクを緩和する保護を一部解除するため、接続先とネットワークのアクセス制御を利用側で確認してください。

  • 環境変数一覧: | 環境変数 | 設定値 | 説明 | | :------------------------------ | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------ | | 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 | 本番環境でローカル・プライベートアドレスへの接続制限を解除する設定。SSRFリスクを緩和する保護が一部解除される(パターンB用) |