UNPKG

streamby-core

Version:

StreamBy middleware framework for media storage management

320 lines (319 loc) 16.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Model = void 0; const connectionManager_1 = require("../adapters/database/connectionManager"); const mongodb_1 = require("mongodb"); const sql_1 = require("../adapters/database/sql"); const nosql_1 = require("../adapters/database/nosql"); class Model { constructor(connectionIds, tableName, schema) { this.connectionIds = connectionIds; this.tableName = tableName; this.schema = schema; } // Add these getter methods getConnectionIds() { return this.connectionIds; } getTableName() { return this.tableName; } useDbType(dbType) { const filteredConnectionIds = this.connectionIds.filter(id => { const connection = (0, connectionManager_1.getConnection)(id); return connection.type === dbType; }); return new Model(filteredConnectionIds, this.tableName); } async find(filter) { const allResults = []; const activeConnectionIds = this.connectionIds.filter(id => (0, connectionManager_1.getConnectedIds)().includes(id)); for (const connectionId of activeConnectionIds) { const clientEntry = (0, connectionManager_1.getConnection)(connectionId); const connection = clientEntry.client; const dbType = clientEntry.type; let processedFilter = { ...filter }; if (dbType === 'sql') { if (processedFilter._id) { processedFilter.id = processedFilter._id; delete processedFilter._id; } let sqlResults = []; if (this.tableName === 'projects' && processedFilter.members && processedFilter.members.$elemMatch) { // Handle members filter for SQL projects const userId = processedFilter.members.$elemMatch.userId; const schema = this.schema || 'streamby'; // Default to 'streamby' if schema not provided const query = ` SELECT p.*, pm."userId" as memberUserId, pm.archived as memberArchived FROM "${schema}"."projects" p JOIN "${schema}"."project_members" pm ON p.id = pm."projectId" WHERE pm."userId" = $1 `; const result = await connection.query(query, [userId]); sqlResults = result.rows.map(row => ({ ...row, members: [{ userId: row.memberUserId, archived: row.memberArchived, // Add other member fields if necessary }] })); } else { // General SQL find sqlResults = await sql_1.sqlAdapter.find(connection, this.tableName, processedFilter, this.schema); } for (const item of sqlResults) { const transformedItem = this.transformResult(item); if (this.tableName === 'projects' && !transformedItem.members) { // For projects, if members not already populated by join, fetch from project_members table const projectMembers = await sql_1.sqlAdapter.find(connection, 'project_members', { projectId: transformedItem.id }, this.schema); transformedItem.members = projectMembers.map((member) => ({ userId: member.userId, role: member.role, // Assuming role is also stored in project_members archived: member.archived, })); } allResults.push(transformedItem); } } else if (dbType === 'nosql') { const nosqlResults = await nosql_1.nosqlAdapter.find(connection, this.tableName, processedFilter); for (const item of nosqlResults) { allResults.push(this.transformResult(item)); } } } return allResults; } transformResult(item) { const transformedItem = { ...item }; if (transformedItem._id && !transformedItem.id) { transformedItem.id = transformedItem._id.toString(); } return transformedItem; } async findOne(filter) { const activeConnectionIds = this.connectionIds.filter(id => (0, connectionManager_1.getConnectedIds)().includes(id)); for (const connectionId of activeConnectionIds) { const clientEntry = (0, connectionManager_1.getConnection)(connectionId); const connection = clientEntry.client; const dbType = clientEntry.type; let processedFilter = { ...filter }; if (dbType === 'sql') { if (processedFilter._id) { processedFilter.id = processedFilter._id; delete processedFilter._id; } // Special handling for 'users' table with raw query if (this.tableName === 'users' && processedFilter.id) { const schema = this.schema || 'streamby'; // Default to 'streamby' if schema not provided const query = `SELECT * FROM "${schema}"."${this.tableName}" WHERE "id" = $1::uuid LIMIT 1`; const result = await connection.query(query, [processedFilter.id]); return result.rows[0] || null; } const result = await sql_1.sqlAdapter.findOne(connection, this.tableName, processedFilter, this.schema); // Pass this.schema if (result) { const transformedResult = this.transformResult(result); if (this.tableName === 'projects') { // For projects, fetch members from project_members table const projectMembers = await sql_1.sqlAdapter.find(connection, 'project_members', { projectId: transformedResult.id }, this.schema); transformedResult.members = projectMembers.map((member) => ({ userId: member.userId, role: member.role, // Assuming role is also stored in project_members archived: member.archived, })); } return transformedResult; } } else if (dbType === 'nosql') { if (processedFilter._id && typeof processedFilter._id === 'string') { try { processedFilter._id = new mongodb_1.ObjectId(processedFilter._id); } catch (e) { // If it's not a valid ObjectId string, it might be a UUID from a SQL project. // In this case, this NoSQL connection won't find it, so we can just continue. continue; } } const result = await nosql_1.nosqlAdapter.findOne(connection, this.tableName, processedFilter); if (result) return result; } } return null; } async create(data) { const activeConnectionIds = this.connectionIds.filter(id => (0, connectionManager_1.getConnectedIds)().includes(id)); // Determine the target database type from the data payload const targetDbType = data.dbType || 'nosql'; // Default to nosql if not specified const allClientEntries = activeConnectionIds.map(id => (0, connectionManager_1.getConnection)(id)); // Find the connection that matches the targetDbType const clientEntry = allClientEntries.find(entry => entry.type === targetDbType); if (!clientEntry) { throw new Error(`No active connection found for database type: ${targetDbType}`); } const connection = clientEntry.client; const dbType = clientEntry.type; if (dbType === 'sql') { const dataToInsert = {}; let membersToInsert = []; // Iterate over the keys of the incoming data for (const key in data) { if (this.tableName === 'projects' && key === 'members') { membersToInsert = data[key]; } else if (this.tableName === 'projects' && key.toLowerCase() === 'dbtype') { dataToInsert["dbType"] = data[key]; } else { dataToInsert[key] = data[key]; } } const created = await sql_1.sqlAdapter.create(connection, this.tableName, dataToInsert, this.schema); // Insert members into project_members table for SQL if (this.tableName === 'projects' && membersToInsert.length > 0) { for (const member of membersToInsert) { await sql_1.sqlAdapter.create(connection, 'project_members', { projectId: created.id, userId: member.userId, role: member.role, archived: member.archived || false, }, this.schema); } } return created; } else if (dbType === 'nosql') { const created = await nosql_1.nosqlAdapter.create(connection, this.tableName, data); return created; } return data; } async update(filter, data) { const existingProject = await this.findOne(filter); // Find the project first if (!existingProject) { return null; // Project not found } const targetDbType = existingProject.dbType; // Get the actual dbType of the project // Find the connection that matches the targetDbType const clientEntry = this.connectionIds .map(id => (0, connectionManager_1.getConnection)(id)) .find(entry => entry.type === targetDbType); if (!clientEntry) { throw new Error(`No active connection found for database type: ${targetDbType}`); } const connection = clientEntry.client; const dbType = clientEntry.type; // This will be the targetDbType let updateFilter = {}; // Initialize updateFilter here // Construct the updateFilter based on the actual dbType of the project if (dbType === 'sql') { updateFilter.id = existingProject.id; // Use the 'id' from the existingProject } else if (dbType === 'nosql') { // Ensure _id is an ObjectId for NoSQL updates if (existingProject._id && typeof existingProject._id === 'string') { try { updateFilter._id = new mongodb_1.ObjectId(existingProject._id); } catch (e) { // If existingProject._id is not a valid ObjectId string, it's an error for NoSQL return null; // Or throw a more specific error } } else { updateFilter._id = existingProject._id; // Already an ObjectId or other valid type } } // Handle specific member archiving/unarchiving if (data["members.$.archived"] !== undefined && filter["_id"] && filter["members.userId"]) { // Use original filter for projectId and userIdToUpdate const originalProjectId = filter["_id"]; // Use the original projectId from the request filter const userIdToUpdate = filter["members.userId"]; const newArchivedStatus = data["members.$.archived"]; const archivedBy = data["members.$.archivedBy"]; const archivedAt = data["members.$.archivedAt"]; if (dbType === 'sql') { // For SQL, directly update the project_members table const memberUpdateResult = await sql_1.sqlAdapter.update(connection, 'project_members', { projectId: originalProjectId, userId: userIdToUpdate }, // originalProjectId is fine for SQL { archived: newArchivedStatus, archivedBy: archivedBy, archivedAt: archivedAt }, this.schema); // After updating the member, fetch the full project to return if (memberUpdateResult) { const updatedProject = await this.findOne({ _id: originalProjectId }); return updatedProject; } } else if (dbType === 'nosql') { const projectToUpdate = existingProject; // Already fetched const updatedMembers = projectToUpdate.members.map((member) => { if (member.userId === userIdToUpdate) { return { ...member, archived: newArchivedStatus, archivedBy: archivedBy, archivedAt: archivedAt }; } return member; }); let objectIdOriginalProjectId; try { objectIdOriginalProjectId = new mongodb_1.ObjectId(originalProjectId); // Convert originalProjectId to ObjectId for NoSQL } catch (e) { return null; } const result = await nosql_1.nosqlAdapter.update(connection, this.tableName, { _id: objectIdOriginalProjectId }, { members: updatedMembers }); if (result) return result; } } else { // General update logic // Use the correctly constructed updateFilter if (dbType === 'sql') { const result = await sql_1.sqlAdapter.update(connection, this.tableName, updateFilter, data, this.schema); if (result) return result; } else if (dbType === 'nosql') { const result = await nosql_1.nosqlAdapter.update(connection, this.tableName, filter, data); if (result) return result; } } return null; } async delete(filter) { let deletedCount = 0; const activeConnectionIds = this.connectionIds.filter(id => (0, connectionManager_1.getConnectedIds)().includes(id)); for (const connectionId of activeConnectionIds) { const clientEntry = (0, connectionManager_1.getConnection)(connectionId); const connection = clientEntry.client; const dbType = clientEntry.type; let processedFilter = { ...filter }; if (dbType === 'sql') { if (processedFilter._id) { processedFilter.id = processedFilter._id; delete processedFilter._id; } console.log(`SQL: Deleting from ${this.tableName} with filter:`, processedFilter); const count = await sql_1.sqlAdapter.delete(connection, this.tableName, processedFilter, this.schema); console.log(`SQL: Deleted ${count} rows from ${this.tableName}`); deletedCount += count; } else if (dbType === 'nosql') { if (processedFilter._id && typeof processedFilter._id === 'string') { try { processedFilter._id = new mongodb_1.ObjectId(processedFilter._id); } catch (e) { // If it's not a valid ObjectId string, it might be a UUID from a SQL project. // In this case, this NoSQL connection won't find it, so we can just continue. continue; } } const count = await nosql_1.nosqlAdapter.delete(connection, this.tableName, processedFilter); deletedCount += count; } } return deletedCount; } } exports.Model = Model;