@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'
});設定オプション
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
origin | string | '' | API オリジン URL |
basePath | string | undefined | API ベースパス(例: /api) |
version | string | 'v1' | API バージョン |
getAccessToken | () => Promise<string | null> | undefined | JWT トークン取得関数 |
fetch | typeof fetch | globalThis.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_request | 400 | リクエストパラメータが不正 |
unauthorized | 401 | 認証エラー |
forbidden | 403 | 権限不足 |
not_found | 404 | リソースが見つからない |
rate_limit | 429 | レート制限超過 |
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_ORIGIN | API オリジン URL |
PUBLIC_DROP_API_VERSION | API バージョン(デフォルト: v1) |
PUBLIC_DROP_API_BASE_PATH | ベースパス(例: /api) |