Skip to content

@dropmov/client

drop.mov API のための型安全な HTTP クライアント SDK です。

インストール

bash
pnpm add @dropmov/client

基本的な使い方

クライアントの初期化

typescript
import { DropClient } from '@dropmov/client';

// 同一オリジン(ブラウザ)での使用
const client = new DropClient({
  getAccessToken: async () => {
    const session = await supabase.auth.getSession();
    return session.data.session?.access_token ?? null;
  },
});

// 外部 API サーバーへの接続
const client = new DropClient({
  origin: 'https://api.drop.mov',
  version: 'v1', // デフォルト: 'v1'
});

設定オプション

オプションデフォルト説明
originstring''API オリジン URL
basePathstringundefinedAPI ベースパス(例: /api
versionstring'v1'API バージョン
getAccessToken() => Promise<string | null>undefinedJWT トークン取得関数
fetchtypeof fetchglobalThis.fetchカスタム fetch 関数

認証コンテキスト

SDK は3つの認証コンテキストを提供します。

User コンテキスト

JWT トークンで認証されたユーザー操作用。

typescript
const userCtx = client.user();

プロフィール

typescript
// ユーザー情報の取得
const { user, tenant, quota } = await userCtx.profile.get();

// 表示名の更新
const { user } = await userCtx.profile.update({ 
  displayName: '新しい名前' 
});

最近のメディア

typescript
const { groups } = await userCtx.recentFiles.list();

グループ作成

typescript
const { groupId, managerToken } = await userCtx.groups.create({
  groupName: 'プロジェクトA',
});

アップロード

typescript
// アップロード開始
const { uploadId, key, mediaSourceId, managerToken } = 
  await userCtx.upload.initiate({
    fileName: 'video.mp4',
    fileType: 'video/mp4',
    fileSize: 1024000,
    groupId: 'group-id',
  });

// パート URL の取得
const { url } = await userCtx.upload.getPartUrl({
  key,
  uploadId,
  partNumber: 1,
  mediaSourceId,
});

// アップロード完了
const { source, group } = await userCtx.upload.complete({
  key,
  uploadId,
  mediaSourceId,
  parts: [{ eTag: 'etag1', partNumber: 1 }],
});

// アップロードキャンセル
await userCtx.upload.cancel({
  key,
  uploadId,
  mediaSourceId,
});

Manager コンテキスト

Manager Token でのメディアグループ管理操作用。

typescript
const managerCtx = client.manager(managerToken);

グループ操作

typescript
// グループ情報の取得
const { group, sources } = await managerCtx.group.get();

// グループ名の更新
const { group } = await managerCtx.group.update({ name: '新しい名前' });

// グループの削除
await managerCtx.group.delete();

メディア操作

typescript
// 再生 URL の取得
const { url } = await managerCtx.media.getPlayUrl(sourceId, {
  key: 'playlist.mpd',
  expires: 1800, // 秒
});

// ダウンロード URL の取得
const { url } = await managerCtx.media.getDownloadUrl(sourceId, {
  key: 'original.mp4',
  filename: 'video.mp4',
});

// 出力一覧の取得
const { outputs } = await managerCtx.media.listOutputs(sourceId);

// 処理状況の取得
const { source, processes } = await managerCtx.media.getProgress(sourceId);

// 再処理のリクエスト
await managerCtx.media.reprocess(sourceId);

// メディアの削除
await managerCtx.media.delete(sourceId);

共有リンク操作

typescript
// 共有リンク一覧の取得
const { shares } = await managerCtx.shares.list();

// 共有リンクの作成
const { viewerToken, share } = await managerCtx.shares.create({
  expiresAt: '2024-12-31T23:59:59Z',
  canDownload: true,
  canViewComment: true,
  canPostComment: false,
});

// 共有リンクの更新
const { share } = await managerCtx.shares.update({
  shareId: 'share-id',
  canDownload: false,
});

// 共有リンクの取り消し
await managerCtx.shares.revoke('share-id');

コメント操作

typescript
// コメント一覧の取得
const { comments } = await managerCtx.comments.list(sourceId);

// コメントの投稿
const { comment } = await managerCtx.comments.create(sourceId, {
  content: 'フィードバックです',
  timestampSeconds: 30,
  parentCommentId: 'parent-id', // 返信の場合
});

// コメントの更新
const { comment } = await managerCtx.comments.update(sourceId, commentId, {
  content: '更新したコメント',
  timestampSeconds: 45,
});

// コメントの削除
await managerCtx.comments.delete(sourceId, commentId);

// リアクションの追加/削除
await managerCtx.comments.react(sourceId, commentId, {
  reactionKey: 'star',
});

Viewer コンテキスト

Viewer Token での共有メディアアクセス用。

typescript
const viewerCtx = client.viewer(viewerToken);

権限に応じて使用可能な操作が制限されます。

グループ情報

typescript
const { group, sources, permissions } = await viewerCtx.group.get();
// permissions: { can_download, can_view_comment, can_post_comment }

メディア操作

typescript
// 再生 URL(常に利用可能)
const { url } = await viewerCtx.media.getPlayUrl(sourceId, {
  key: 'playlist.mpd',
});

// ダウンロード URL(can_download が必要)
const { url } = await viewerCtx.media.getDownloadUrl(sourceId, {
  key: 'original.mp4',
});

コメント操作

typescript
// コメント一覧(can_view_comment が必要)
const { comments } = await viewerCtx.comments.list(sourceId);

// コメント投稿(can_post_comment + サインインが必要)
const { comment } = await viewerCtx.comments.create(sourceId, {
  content: 'コメント',
  timestampSeconds: 30,
});

エラーハンドリング

typescript
import { ApiError, isApiError } from '@dropmov/client';

try {
  await managerCtx.comments.create(sourceId, { content: '' });
} catch (error) {
  if (isApiError(error)) {
    console.error(error.message);      // エラーメッセージ
    console.error(error.statusCode);   // HTTP ステータスコード
    console.error(error.errorType);    // エラータイプ
    console.error(error.responseBody); // レスポンス全体
  }
}

エラータイプ

エラータイプステータス説明
bad_request400リクエストパラメータが不正
unauthorized401認証エラー
forbidden403権限不足
not_found404リソースが見つからない
rate_limit429レート制限超過

AbortSignal のサポート

すべてのメソッドで AbortSignal によるリクエストキャンセルが可能です:

typescript
const controller = new AbortController();

const promise = managerCtx.comments.list(sourceId, {
  signal: controller.signal,
});

// キャンセル
controller.abort();

カスタム fetch

テストや SSR 環境ではカスタム fetch 関数を指定できます:

typescript
// テスト用
const mockFetch = vi.fn();
const client = new DropClient({
  origin: 'https://api.drop.mov',
  fetch: mockFetch,
});

// SSR でカスタムヘッダーを追加
const client = new DropClient({
  origin: process.env.DROP_API_ORIGIN,
  fetch: (url, init) => fetch(url, {
    ...init,
    headers: {
      ...init?.headers,
      'X-Request-Id': requestId,
    },
  }),
});

Astro プロジェクトでの使用

環境変数を使用した設定:

typescript
const client = new DropClient({
  origin: import.meta.env.PUBLIC_DROP_API_ORIGIN,
  version: import.meta.env.PUBLIC_DROP_API_VERSION,
  basePath: import.meta.env.PUBLIC_DROP_API_BASE_PATH,
});
環境変数説明
PUBLIC_DROP_API_ORIGINAPI オリジン URL
PUBLIC_DROP_API_VERSIONAPI バージョン(デフォルト: v1
PUBLIC_DROP_API_BASE_PATHベースパス(例: /api

drop.mov ― a kumo™ product