import { z } from 'zod'; /** Valid storage tier values */ export const StorageTierValues = ['STANDARD', 'INFREQUENT_ACCESS', 'ARCHIVE'] as const; /** Storage tier enum schema */ export const StorageTierSchema = z .enum(StorageTierValues) .describe('Storage tier: `STANDARD`, `INFREQUENT_ACCESS`, or `ARCHIVE`'); /** Storage tier type */ export type StorageTier = z.infer; /** CORS configuration for a bucket */ export const CORSConfigSchema = z.object({ allowed_origins: z .array(z.string().describe('An allowed origin URL')) .optional() .describe('List of allowed origin URLs for CORS requests'), allowed_methods: z .array(z.string().describe('An allowed HTTP method')) .optional() .describe('List of allowed HTTP methods for CORS requests'), allowed_headers: z .array(z.string().describe('An allowed request header')) .optional() .describe('List of allowed request headers for CORS requests'), expose_headers: z .array(z.string().describe('A response header to expose')) .optional() .describe('List of response headers to expose to the browser'), max_age_seconds: z .number() .int() .min(0) .nullable() .optional() .describe('Maximum time in seconds that preflight results can be cached'), }); /** Full bucket config (response from GET/PUT) */ export const BucketConfigSchema = z.object({ bucket_name: z.string().describe('The name of the storage bucket'), storage_tier: StorageTierSchema.nullable() .optional() .describe('Storage tier: `STANDARD`, `INFREQUENT_ACCESS`, or `ARCHIVE`'), ttl: z.number().int().min(0).nullable().optional().describe('Object TTL in seconds'), public: z.boolean().nullable().optional().describe('Whether the bucket is publicly accessible'), cache_control: z .string() .nullable() .optional() .describe('Default Cache-Control header for objects'), cors: CORSConfigSchema.nullable().optional().describe('Custom CORS configuration'), additional_headers: z .record(z.string(), z.string()) .nullable() .optional() .describe('Additional response headers as key-value pairs'), bucket_location: z.string().nullable().optional().describe('Bucket location or region override'), }); /** * Update request body (all fields optional — partial update). * Send a field with a value to set it, send null to unset it, omit to leave unchanged. */ export const BucketConfigUpdateSchema = z.object({ storage_tier: StorageTierSchema.nullable() .optional() .describe('Storage tier: `STANDARD`, `INFREQUENT_ACCESS`, or `ARCHIVE`'), ttl: z .number() .int() .min(0) .nullable() .optional() .describe('Object TTL in seconds (0 to clear)'), public: z.boolean().nullable().optional().describe('Whether the bucket is publicly accessible'), cache_control: z .string() .nullable() .optional() .describe('Default Cache-Control header for objects'), cors: CORSConfigSchema.nullable().optional().describe('Custom CORS configuration'), additional_headers: z .record(z.string(), z.string()) .nullable() .optional() .describe('Additional response headers as key-value pairs'), }); /** TypeScript types derived from Zod schemas */ export type CORSConfig = z.infer; export type BucketConfig = z.infer; export type BucketConfigUpdate = z.infer; // --- Storage Objects types --- /** A storage object in a bucket */ export const StorageObjectSchema = z.object({ bucket_name: z.string().describe('The bucket this object belongs to'), key: z.string().describe('Object key (path)'), size: z.number().int().nonnegative().describe('Object size in bytes'), etag: z.string().optional().describe('Object ETag'), content_type: z.string().optional().describe('Object content type'), last_modified: z.string().optional().describe('Last modified timestamp (ISO8601)'), }); /** Paginated list of storage objects */ export const StorageListResponseSchema = z.object({ objects: z.array(StorageObjectSchema).describe('List of objects'), total: z.number().int().nonnegative().describe('Total count matching the query'), prefix: z.string().describe('Prefix filter applied'), limit: z.number().int().nonnegative().describe('Page size'), offset: z.number().int().nonnegative().describe('Page offset'), }); /** Delete response */ export const StorageDeleteResponseSchema = z.object({ deleted_count: z.number().int().nonnegative().describe('Number of objects deleted'), }); /** Presigned URL response */ export const StoragePresignResponseSchema = z.object({ presigned_url: z.string().describe('The presigned URL'), expiry_seconds: z.number().int().nonnegative().describe('URL expiry time in seconds'), }); /** Bucket stats response */ export const StorageStatsResponseSchema = z.object({ bucket_name: z.string().describe('The bucket name'), object_count: z.number().int().nonnegative().describe('Number of objects'), total_size: z.number().int().nonnegative().describe('Total size in bytes'), last_event_at: z.string().optional().describe('Last event timestamp (ISO8601)'), }); // --- Storage Analytics types --- /** Summary totals across all buckets */ export const StorageAnalyticsSummarySchema = z.object({ total_object_count: z.number().int().nonnegative().describe('Total objects across all buckets'), total_size: z.number().int().nonnegative().describe('Total size in bytes across all buckets'), estimated_monthly_cost: z.number().describe('Estimated monthly cost in USD'), cost_per_gb_month: z.number().describe('Cost rate per GB per month in USD'), }); /** Per-bucket breakdown */ export const StorageAnalyticsBucketSchema = z.object({ bucket_name: z.string().describe('The bucket name'), object_count: z.number().int().nonnegative().describe('Number of objects in this bucket'), total_size: z.number().int().nonnegative().describe('Total size in bytes for this bucket'), last_event_at: z.string().optional().describe('Last event timestamp (ISO8601)'), estimated_monthly_cost: z.number().describe('Estimated monthly cost for this bucket in USD'), }); /** Daily snapshot for sparklines */ export const StorageAnalyticsDailySnapshotSchema = z.object({ date: z.string().describe('Snapshot date (YYYY-MM-DD)'), total_object_count: z.number().int().nonnegative().describe('Total objects on this date'), total_size: z.number().int().nonnegative().describe('Total size in bytes on this date'), estimated_cost: z.number().describe('Estimated monthly cost at this snapshot in USD'), }); /** Full analytics response */ export const StorageAnalyticsResponseSchema = z.object({ summary: StorageAnalyticsSummarySchema.describe('Org-wide totals'), buckets: z.array(StorageAnalyticsBucketSchema).describe('Per-bucket breakdown'), daily: z.array(StorageAnalyticsDailySnapshotSchema).describe('Daily snapshots for sparklines'), days: z.number().int().nonnegative().describe('Number of days requested'), }); export type StorageObject = z.infer; export type StorageListResponse = z.infer; export type StorageDeleteResponse = z.infer; export type StoragePresignResponse = z.infer; export type StorageStatsResponse = z.infer; export type StorageAnalyticsSummary = z.infer; export type StorageAnalyticsBucket = z.infer; export type StorageAnalyticsDailySnapshot = z.infer; export type StorageAnalyticsResponse = z.infer;