// Platform-level bucket management. // Backend: /api/v1/platform/buckets/*. All operations require a // storage_config_id pointing at a credential row in /api/v1/storage_configs. import type { ArcadiaClient } from "@crema/arcadia-client" export interface Bucket { name: string region?: string size_bytes?: number | null object_count?: number | null created_at?: string | null /** Backend may return additional provider-specific fields. */ [key: string]: unknown } export interface BucketObject { key: string size: number last_modified: string | null etag: string | null storage_class: string | null } export interface ListObjectsResponse { objects: BucketObject[] is_truncated: boolean continuation_token: string | null prefix: string | null bucket_name: string } export interface CreateBucketInput { storage_config_id: string bucket_name: string region?: string acl?: "private" | "public-read" | string versioning?: boolean /** Pre-validate without creating. Default false. */ dry_run?: boolean } export interface DeleteBucketInput { storage_config_id: string bucket_name: string /** 6-digit code from /confirmation-code. */ confirmation_code?: string /** DANGEROUS — empty the bucket first. */ force_empty?: boolean /** Verify a backup exists before delete. Default true. */ verify_backup?: boolean /** Preview-only. Default true on first call so the UI can confirm. */ dry_run?: boolean } const BASE = "/api/v1/platform/buckets" export async function listBuckets( arcadia: ArcadiaClient, storageConfigId: string, ): Promise { const res = await arcadia.GET<{ buckets: Bucket[]; count: number }>(`${BASE}/list`, { params: { storage_config_id: storageConfigId }, }) return res.buckets ?? [] } export async function createBucket( arcadia: ArcadiaClient, input: CreateBucketInput, ): Promise { return arcadia.POST(`${BASE}/create`, { body: input }) } export async function deleteBucket( arcadia: ArcadiaClient, input: DeleteBucketInput, ): Promise { return arcadia.POST(`${BASE}/delete`, { body: input }) } export async function generateConfirmationCode( arcadia: ArcadiaClient, storageConfigId: string, bucketName: string, ): Promise<{ code: string; expires_at?: string }> { return arcadia.GET(`${BASE}/confirmation-code`, { params: { storage_config_id: storageConfigId, bucket_name: bucketName }, }) } export async function listRegions( arcadia: ArcadiaClient, storageConfigId: string, ): Promise { const res = await arcadia.GET<{ regions?: string[]; data?: string[] }>(`${BASE}/regions`, { params: { storage_config_id: storageConfigId }, }) return res.regions ?? res.data ?? [] } // --- Versioning / lifecycle / replication / policy / CORS ----------------- export async function configureVersioning( arcadia: ArcadiaClient, input: { storage_config_id: string; bucket_name: string; enabled: boolean; dry_run?: boolean }, ): Promise { return arcadia.POST(`${BASE}/versioning`, { body: input }) } export async function configureLifecycle( arcadia: ArcadiaClient, input: { storage_config_id: string bucket_name: string rules: Array> dry_run?: boolean }, ): Promise { return arcadia.POST(`${BASE}/lifecycle`, { body: input }) } export async function configureReplication( arcadia: ArcadiaClient, input: { storage_config_id: string bucket_name: string destination_bucket: string destination_region?: string dry_run?: boolean }, ): Promise { return arcadia.POST(`${BASE}/replication`, { body: input }) } export async function configurePolicy( arcadia: ArcadiaClient, input: { storage_config_id: string bucket_name: string policy: Record dry_run?: boolean }, ): Promise { return arcadia.POST(`${BASE}/policy`, { body: input }) } export interface CorsRule { allowed_origins: string[] allowed_methods: string[] allowed_headers?: string[] expose_headers?: string[] max_age_seconds?: number } export async function getCors( arcadia: ArcadiaClient, storageConfigId: string, bucketName: string, ): Promise<{ rules: CorsRule[] } | null> { return arcadia.GET(`${BASE}/cors`, { params: { storage_config_id: storageConfigId, bucket_name: bucketName }, }) } export async function configureCors( arcadia: ArcadiaClient, input: { storage_config_id: string bucket_name: string rules: CorsRule[] dry_run?: boolean }, ): Promise { return arcadia.POST(`${BASE}/cors`, { body: input }) } export async function deleteCors( arcadia: ArcadiaClient, storageConfigId: string, bucketName: string, ): Promise { return arcadia.DELETE(`${BASE}/cors`, { params: { storage_config_id: storageConfigId, bucket_name: bucketName }, }) } // --- Objects --------------------------------------------------------------- export async function listObjects( arcadia: ArcadiaClient, params: { storage_config_id: string bucket_name: string prefix?: string max_keys?: number continuation_token?: string }, ): Promise { return arcadia.GET(`${BASE}/objects`, { params: params as Record, }) } export async function getPresignedUrl( arcadia: ArcadiaClient, params: { storage_config_id: string bucket_name: string key: string expires_in?: number }, ): Promise<{ url: string; expires_at?: string; expires_in?: number }> { return arcadia.GET(`${BASE}/presigned-url`, { params: params as Record, }) }