Add new video attributes and improve storage management
Implement a hybrid storage solution combining Bunny.net for video operations and PostgreSQL for user data. Update video schema with face detection and content type fields, and add a `isSuperAdmin` flag for user roles. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 22c71427-e484-49cc-bab4-5c9a7f7d98bc Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/22c71427-e484-49cc-bab4-5c9a7f7d98bc/JP4XKDb
This commit is contained in:
parent
c71720454f
commit
e394e3f671
1
.replit
1
.replit
@ -40,4 +40,3 @@ args = "npm run dev"
|
||||
waitForPort = 5000
|
||||
|
||||
[agent]
|
||||
integrations = ["javascript_database==1.0.0", "javascript_log_in_with_replit==1.0.0", "javascript_object_storage==1.0.0"]
|
||||
|
||||
@ -391,11 +391,16 @@ export class MemStorage implements IStorage {
|
||||
description: video.description || "",
|
||||
category: video.category || "",
|
||||
customThumbnailUrl: null,
|
||||
faceCenterPosition: null,
|
||||
facesDetected: 0,
|
||||
faceConfidence: 0,
|
||||
videoUrlMp4: null,
|
||||
videoUrlIframe: null,
|
||||
tags: [],
|
||||
isPublic: true,
|
||||
views: video.views || 0,
|
||||
contentType: video.contentType || 'video',
|
||||
genre: video.genre || 'other',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
uploadStatus: video.uploadStatus || "completed",
|
||||
@ -442,11 +447,16 @@ export class MemStorage implements IStorage {
|
||||
description: video.description || "",
|
||||
category: video.category || "",
|
||||
customThumbnailUrl: null,
|
||||
faceCenterPosition: null,
|
||||
facesDetected: 0,
|
||||
faceConfidence: 0,
|
||||
videoUrlMp4: null,
|
||||
videoUrlIframe: null,
|
||||
tags: video.tags || [],
|
||||
isPublic: video.isPublic ?? true,
|
||||
views: video.views || 0,
|
||||
contentType: video.contentType || 'video',
|
||||
genre: video.genre || 'other',
|
||||
uploadStatus: video.uploadStatus || "completed",
|
||||
originalFileName: video.originalFileName || null,
|
||||
fileSize: video.fileSize || null,
|
||||
@ -526,6 +536,7 @@ export class MemStorage implements IStorage {
|
||||
lastName: user.lastName || null,
|
||||
profileImageUrl: user.profileImageUrl || null,
|
||||
isAdmin: user.isAdmin ?? false,
|
||||
isSuperAdmin: user.isSuperAdmin ?? false,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
};
|
||||
@ -770,8 +781,8 @@ class BunnyStorage implements IStorage {
|
||||
}
|
||||
|
||||
// Update views cache
|
||||
if (views !== undefined) {
|
||||
this.viewsCache.set(id, (this.viewsCache.get(id) || 0) + (views - (this.viewsCache.get(id) || 0)));
|
||||
if (views !== undefined && typeof views === 'number') {
|
||||
this.viewsCache.set(id, views);
|
||||
}
|
||||
|
||||
// Return updated video
|
||||
@ -899,14 +910,145 @@ class BunnyStorage implements IStorage {
|
||||
}
|
||||
}
|
||||
|
||||
// Storage selection logic - choose DatabaseStorage if PostgreSQL is available
|
||||
// Hybrid storage implementation that uses Bunny.net for videos and Database for users
|
||||
export class HybridStorage implements IStorage {
|
||||
private bunnyStorage: BunnyStorage;
|
||||
private databaseStorage: DatabaseStorage;
|
||||
|
||||
constructor() {
|
||||
this.bunnyStorage = new BunnyStorage();
|
||||
this.databaseStorage = new DatabaseStorage();
|
||||
}
|
||||
|
||||
// Video operations - use Bunny.net
|
||||
async getVideos(limit?: number, offset?: number, search?: string): Promise<Video[]> {
|
||||
return this.bunnyStorage.getVideos(limit, offset, search);
|
||||
}
|
||||
|
||||
async getVideo(id: string): Promise<Video | undefined> {
|
||||
return this.bunnyStorage.getVideo(id);
|
||||
}
|
||||
|
||||
async createVideo(video: InsertVideo): Promise<Video> {
|
||||
return this.bunnyStorage.createVideo(video);
|
||||
}
|
||||
|
||||
async updateVideo(id: string, video: UpdateVideo): Promise<Video | undefined> {
|
||||
return this.bunnyStorage.updateVideo(id, video);
|
||||
}
|
||||
|
||||
async updateVideoViews(id: string): Promise<void> {
|
||||
return this.bunnyStorage.updateVideoViews(id);
|
||||
}
|
||||
|
||||
async getVideoCount(search?: string): Promise<number> {
|
||||
return this.bunnyStorage.getVideoCount(search);
|
||||
}
|
||||
|
||||
async deleteVideo(id: string): Promise<boolean> {
|
||||
return this.bunnyStorage.deleteVideo(id);
|
||||
}
|
||||
|
||||
// User operations - use Database
|
||||
async getUser(id: string): Promise<User | undefined> {
|
||||
return this.databaseStorage.getUser(id);
|
||||
}
|
||||
|
||||
async getUserByEmail(email: string): Promise<User | undefined> {
|
||||
return this.databaseStorage.getUserByEmail(email);
|
||||
}
|
||||
|
||||
async getUserByUsername(username: string): Promise<User | undefined> {
|
||||
return this.databaseStorage.getUserByUsername(username);
|
||||
}
|
||||
|
||||
async createUser(user: InsertUser): Promise<User> {
|
||||
return this.databaseStorage.createUser(user);
|
||||
}
|
||||
|
||||
async updateUser(id: string, user: Partial<InsertUser>): Promise<User | undefined> {
|
||||
return this.databaseStorage.updateUser(id, user);
|
||||
}
|
||||
|
||||
async upsertUser(user: any): Promise<User> {
|
||||
return this.databaseStorage.upsertUser(user);
|
||||
}
|
||||
|
||||
async validateUserPassword(email: string, password: string): Promise<User | null> {
|
||||
return this.databaseStorage.validateUserPassword(email, password);
|
||||
}
|
||||
|
||||
// Upload operations - use Database
|
||||
async createVideoUpload(upload: InsertVideoUpload): Promise<VideoUpload> {
|
||||
return this.databaseStorage.createVideoUpload(upload);
|
||||
}
|
||||
|
||||
async getVideoUpload(id: string): Promise<VideoUpload | undefined> {
|
||||
return this.databaseStorage.getVideoUpload(id);
|
||||
}
|
||||
|
||||
async updateVideoUpload(id: string, upload: Partial<InsertVideoUpload>): Promise<VideoUpload | undefined> {
|
||||
return this.databaseStorage.updateVideoUpload(id, upload);
|
||||
}
|
||||
|
||||
async getUserVideoUploads(userId: string): Promise<VideoUpload[]> {
|
||||
return this.databaseStorage.getUserVideoUploads(userId);
|
||||
}
|
||||
|
||||
// Category operations - use Database
|
||||
async getCategories(): Promise<Category[]> {
|
||||
return this.databaseStorage.getCategories();
|
||||
}
|
||||
|
||||
async createCategory(category: InsertCategory): Promise<Category> {
|
||||
return this.databaseStorage.createCategory(category);
|
||||
}
|
||||
|
||||
async updateCategory(id: string, category: Partial<InsertCategory>): Promise<Category | undefined> {
|
||||
return this.databaseStorage.updateCategory(id, category);
|
||||
}
|
||||
|
||||
async deleteCategory(id: string): Promise<boolean> {
|
||||
return this.databaseStorage.deleteCategory(id);
|
||||
}
|
||||
|
||||
// Tag operations - use Database
|
||||
async getTags(): Promise<Tag[]> {
|
||||
return this.databaseStorage.getTags();
|
||||
}
|
||||
|
||||
async getPopularTags(limit?: number): Promise<Tag[]> {
|
||||
return this.databaseStorage.getPopularTags(limit);
|
||||
}
|
||||
|
||||
async createTag(tag: InsertTag): Promise<Tag> {
|
||||
return this.databaseStorage.createTag(tag);
|
||||
}
|
||||
|
||||
async incrementTagUse(name: string): Promise<void> {
|
||||
return this.databaseStorage.incrementTagUse(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Storage selection logic - use hybrid approach when both Bunny.net and Database are available
|
||||
let storage: IStorage;
|
||||
|
||||
const hasDatabase = process.env.DATABASE_URL;
|
||||
const hasBunnyConfig = process.env.BUNNY_API_KEY && process.env.BUNNY_LIBRARY_ID && process.env.BUNNY_HOSTNAME;
|
||||
|
||||
// Prioritize Bunny.net storage for user's video content
|
||||
if (hasBunnyConfig) {
|
||||
// Use hybrid storage when both Bunny.net and Database are available
|
||||
if (hasBunnyConfig && hasDatabase) {
|
||||
try {
|
||||
storage = new HybridStorage();
|
||||
console.log('✅ Using Hybrid storage (Bunny.net for videos + Database for users)');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to initialize Hybrid storage:', error);
|
||||
console.log('📁 Falling back to memory storage');
|
||||
storage = new MemStorage();
|
||||
}
|
||||
}
|
||||
// Prioritize Bunny.net storage for video content only
|
||||
else if (hasBunnyConfig) {
|
||||
try {
|
||||
storage = new BunnyStorage();
|
||||
console.log('✅ Using Bunny.net storage with library ID:', process.env.BUNNY_LIBRARY_ID);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user