@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
444 lines (386 loc) • 9.14 kB
text/typescript
// =============================================================================
// Media Management System Types
// =============================================================================
export interface MediaFile {
id: string;
filename: string;
originalName: string;
mimeType: string;
size: number;
url: string;
path: string;
// Processing status
processed: boolean;
processingStatus: ProcessingStatus;
optimizedUrl?: string;
thumbnailUrl?: string;
webpUrl?: string;
// Image metadata
width?: number;
height?: number;
aspectRatio?: number;
colorProfile?: string;
// Security
checksum?: string;
virusScanned: boolean;
scanResult?: ScanResult;
isPublic: boolean;
accessLevel: AccessLevel;
// Organization
folderId?: string;
folder?: MediaFolder;
collections: MediaCollection[];
tags: MediaTag[];
// Content metadata
alt?: string;
caption?: string;
title?: string;
description?: string;
metadata?: Record<string, unknown>;
// Usage tracking
downloadCount: number;
viewCount: number;
lastAccessed?: Date;
// CDN
cdnUrl?: string;
cdnProvider?: string;
cacheStatus?: CacheStatus;
// Relationships
userId?: string;
siteId?: string;
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface MediaFolder {
id: string;
name: string;
slug: string;
description?: string;
path: string;
// Hierarchy
parentId?: string;
parent?: MediaFolder;
children: MediaFolder[];
// Access control
isPublic: boolean;
permissions?: Record<string, unknown>;
// Relationships
siteId?: string;
userId: string;
uploads: MediaFile[];
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface MediaCollection {
id: string;
name: string;
slug: string;
description?: string;
color?: string;
// Settings
isPublic: boolean;
isFeatured: boolean;
// Relationships
siteId?: string;
userId: string;
uploads: MediaFile[];
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface MediaTag {
id: string;
name: string;
slug: string;
color?: string;
description?: string;
// Relationships
siteId?: string;
usageCount: number;
uploads: MediaFile[];
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface MediaProcessingJob {
id: string;
uploadId: string;
upload: MediaFile;
// Job details
type: ProcessingJobType;
status: JobStatus;
priority: number;
// Configuration
params?: Record<string, unknown>;
// Results
result?: Record<string, unknown>;
error?: string;
// Processing info
startedAt?: Date;
completedAt?: Date;
attempts: number;
maxAttempts: number;
workerId?: string;
// Timestamps
createdAt: Date;
updatedAt: Date;
}
export interface MediaUsageAnalytics {
id: string;
uploadId: string;
upload: MediaFile;
// Context
referrer?: string;
userAgent?: string;
ipAddress?: string;
country?: string;
action: UsageAction;
// Site context
siteId?: string;
// Timestamp
timestamp: Date;
}
// =============================================================================
// Enums
// =============================================================================
export enum ProcessingStatus {
PENDING = "pending",
PROCESSING = "processing",
COMPLETED = "completed",
FAILED = "failed",
}
export enum ScanResult {
CLEAN = "clean",
INFECTED = "infected",
ERROR = "error",
}
export enum AccessLevel {
PUBLIC = "public",
PRIVATE = "private",
RESTRICTED = "restricted",
}
export enum CacheStatus {
CACHED = "cached",
PURGED = "purged",
PENDING = "pending",
}
export enum ProcessingJobType {
RESIZE = "resize",
OPTIMIZE = "optimize",
CONVERT = "convert",
SCAN = "scan",
THUMBNAIL = "thumbnail",
WEBP_CONVERSION = "webp_conversion",
WATERMARK = "watermark",
}
export enum JobStatus {
PENDING = "pending",
PROCESSING = "processing",
COMPLETED = "completed",
FAILED = "failed",
CANCELLED = "cancelled",
}
export enum UsageAction {
VIEW = "view",
DOWNLOAD = "download",
EMBED = "embed",
THUMBNAIL = "thumbnail",
PREVIEW = "preview",
}
// =============================================================================
// Upload and API Types
// =============================================================================
export interface UploadRequest {
file: File;
folderId?: string;
collections?: string[];
tags?: string[];
alt?: string;
caption?: string;
title?: string;
description?: string;
isPublic?: boolean;
accessLevel?: AccessLevel;
}
export interface UploadResponse {
success: boolean;
data?: MediaFile;
error?: string;
jobId?: string; // For async processing
}
export interface UploadProgress {
uploadId: string;
progress: number; // 0-100
status: "uploading" | "processing" | "completed" | "error";
message?: string;
bytesUploaded: number;
totalBytes: number;
speed?: number; // bytes per second
eta?: number; // seconds remaining
}
export interface BatchUploadRequest {
files: File[];
folderId?: string;
collections?: string[];
tags?: string[];
defaultMetadata?: {
alt?: string;
caption?: string;
title?: string;
description?: string;
};
isPublic?: boolean;
accessLevel?: AccessLevel;
}
export interface BatchUploadProgress {
totalFiles: number;
completedFiles: number;
failedFiles: number;
currentFile?: string;
overallProgress: number; // 0-100
fileProgresses: Record<string, UploadProgress>;
}
// =============================================================================
// Search and Filter Types
// =============================================================================
export interface MediaSearchFilters {
query?: string;
mimeTypes?: string[];
tags?: string[];
collections?: string[];
folderId?: string;
dateRange?: {
start: Date;
end: Date;
};
sizeRange?: {
min: number;
max: number;
};
dimensions?: {
minWidth?: number;
maxWidth?: number;
minHeight?: number;
maxHeight?: number;
};
processed?: boolean;
isPublic?: boolean;
accessLevel?: AccessLevel;
}
export interface MediaSearchOptions {
limit?: number;
offset?: number;
sortBy?:
| "createdAt"
| "updatedAt"
| "size"
| "name"
| "viewCount"
| "downloadCount";
sortOrder?: "asc" | "desc";
includeFolders?: boolean;
includeCollections?: boolean;
includeTags?: boolean;
}
export interface MediaSearchResult {
files: MediaFile[];
folders?: MediaFolder[];
collections?: MediaCollection[];
tags?: MediaTag[];
total: number;
hasMore: boolean;
facets?: {
mimeTypes: Record<string, number>;
tags: Record<string, number>;
collections: Record<string, number>;
folders: Record<string, number>;
};
}
// =============================================================================
// UI Component Types
// =============================================================================
export interface MediaLibraryProps {
siteId?: string;
multiSelect?: boolean;
allowUpload?: boolean;
allowFolders?: boolean;
allowCollections?: boolean;
allowTags?: boolean;
maxSelections?: number;
acceptedTypes?: string[];
onSelect?: (files: MediaFile[]) => void;
onUpload?: (files: MediaFile[]) => void;
className?: string;
}
export interface MediaPickerProps {
isOpen: boolean;
onClose: () => void;
onSelect: (files: MediaFile[]) => void;
multiSelect?: boolean;
acceptedTypes?: string[];
maxSelections?: number;
siteId?: string;
}
export interface MediaGridProps {
files: MediaFile[];
selectedFiles?: MediaFile[];
onSelect?: (files: MediaFile[]) => void;
onPreview?: (file: MediaFile) => void;
multiSelect?: boolean;
viewMode?: "grid" | "list";
className?: string;
}
export interface MediaUploadZoneProps {
onUpload: (files: File[]) => void;
onProgress?: (progress: BatchUploadProgress) => void;
acceptedTypes?: string[];
maxFileSize?: number;
maxFiles?: number;
disabled?: boolean;
className?: string;
}
// =============================================================================
// Configuration Types
// =============================================================================
export interface MediaConfig {
storage: {
provider: "local" | "aws" | "gcp" | "azure";
bucket?: string;
region?: string;
path?: string;
maxFileSize: number;
allowedTypes: string[];
};
processing: {
enabled: boolean;
thumbnailSizes: number[];
webpConversion: boolean;
qualitySettings: {
jpeg: number;
webp: number;
png: number;
};
};
cdn: {
enabled: boolean;
provider?: "cloudflare" | "aws" | "gcp";
domain?: string;
cacheHeaders: Record<string, string>;
};
security: {
virusScanning: boolean;
checksumValidation: boolean;
signedUrls: boolean;
maxQuotaPerSite: number;
maxQuotaPerUser: number;
};
features: {
folders: boolean;
collections: boolean;
tags: boolean;
analytics: boolean;
watermarking: boolean;
};
}