feat(packs): lib helpers — pack-files supabase 쿼리 + web-backend HMAC 클라이언트

- pack-files.ts: tier hierarchy + getPackFilesForTiers + getPackFileById
- web-backend.ts: signLink (HMAC sig) + mintUploadToken (일회성 jti, 15분 만료)
  + listPackFilesViaBackend + deletePackFileViaBackend

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 09:00:30 +09:00
parent ace46fb2ae
commit 3e64030239
2 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
import type { SupabaseClient } from '@supabase/supabase-js';
import type { PackTier } from '../pack-assets';
export interface PackFile {
id: string;
min_tier: PackTier;
label: string;
file_path: string;
filename: string;
size_bytes: number;
sort_order: number;
uploaded_at: string;
deleted_at: string | null;
}
const TIER_HIERARCHY: Record<PackTier, PackTier[]> = {
starter: ['starter'],
pro: ['starter', 'pro'],
master: ['starter', 'pro', 'master'],
};
export function tierIncludes(userTier: PackTier): PackTier[] {
return TIER_HIERARCHY[userTier];
}
export async function getPackFilesForTiers(
supabase: SupabaseClient,
tiers: PackTier[],
): Promise<PackFile[]> {
if (tiers.length === 0) return [];
const { data, error } = await supabase
.from('pack_files')
.select('*')
.in('min_tier', tiers)
.is('deleted_at', null)
.order('min_tier')
.order('sort_order');
if (error) throw error;
return (data ?? []) as PackFile[];
}
export async function getPackFileById(
supabase: SupabaseClient,
id: string,
): Promise<PackFile | null> {
const { data, error } = await supabase
.from('pack_files')
.select('*')
.eq('id', id)
.is('deleted_at', null)
.maybeSingle();
if (error) throw error;
return (data as PackFile) ?? null;
}