backend: simplify repository classes by removing generic types and enhancing type handling
This commit is contained in:
parent
83583259ba
commit
27d4249c57
@ -1,39 +1,36 @@
|
||||
import { MeetApiKey } from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { Require_id } from 'mongoose';
|
||||
import { MeetApiKeyDocument, MeetApiKeyModel } from '../models/mongoose-schemas/api-key.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
import { BaseRepository } from './base.repository.js';
|
||||
|
||||
/**
|
||||
* Repository for managing MeetApiKey entities in MongoDB.
|
||||
*
|
||||
* @template TApiKey - The domain type extending MeetApiKey (default: MeetApiKey)
|
||||
*/
|
||||
@injectable()
|
||||
export class ApiKeyRepository<TApiKey extends MeetApiKey = MeetApiKey> extends BaseRepository<
|
||||
TApiKey,
|
||||
MeetApiKeyDocument
|
||||
> {
|
||||
export class ApiKeyRepository extends BaseRepository<MeetApiKey, MeetApiKeyDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetApiKeyModel);
|
||||
}
|
||||
|
||||
protected toDomain(document: MeetApiKeyDocument): TApiKey {
|
||||
return document.toObject() as TApiKey;
|
||||
protected toDomain(dbObject: Require_id<MeetApiKeyDocument> & { __v: number }): MeetApiKey {
|
||||
const { _id, __v, schemaVersion, ...apiKey } = dbObject;
|
||||
(void _id, __v, schemaVersion);
|
||||
return apiKey as MeetApiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new API key.
|
||||
*/
|
||||
async create(apiKey: TApiKey): Promise<TApiKey> {
|
||||
const doc = await this.createDocument(apiKey);
|
||||
return this.toDomain(doc);
|
||||
async create(apiKey: MeetApiKey): Promise<MeetApiKey> {
|
||||
return this.createDocument(apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all API keys.
|
||||
*/
|
||||
async findAll(): Promise<TApiKey[]> {
|
||||
async findAll(): Promise<MeetApiKey[]> {
|
||||
return await super.findAll();
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { GlobalConfig } from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { Require_id } from 'mongoose';
|
||||
import { MeetGlobalConfigDocument, MeetGlobalConfigModel } from '../models/mongoose-schemas/global-config.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
import { BaseRepository } from './base.repository.js';
|
||||
@ -9,26 +10,17 @@ import { BaseRepository } from './base.repository.js';
|
||||
*
|
||||
* IMPORTANT: This collection should only contain ONE document representing the
|
||||
* system-wide global configuration. Methods are designed to work with this singleton pattern.
|
||||
*
|
||||
* @template TGlobalConfig - The domain type extending GlobalConfig (default: GlobalConfig)
|
||||
*/
|
||||
@injectable()
|
||||
export class GlobalConfigRepository<TGlobalConfig extends GlobalConfig = GlobalConfig> extends BaseRepository<
|
||||
TGlobalConfig,
|
||||
MeetGlobalConfigDocument
|
||||
> {
|
||||
export class GlobalConfigRepository extends BaseRepository<GlobalConfig, MeetGlobalConfigDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetGlobalConfigModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a MongoDB document into a domain GlobalConfig object.
|
||||
*
|
||||
* @param document - The MongoDB document
|
||||
* @returns GlobalConfig domain object
|
||||
*/
|
||||
protected toDomain(document: MeetGlobalConfigDocument): TGlobalConfig {
|
||||
return document.toObject() as TGlobalConfig;
|
||||
protected toDomain(dbObject: Require_id<MeetGlobalConfigDocument> & { __v: number }): GlobalConfig {
|
||||
const { _id, __v, schemaVersion, ...globalConfig } = dbObject;
|
||||
(void _id, __v, schemaVersion);
|
||||
return globalConfig as GlobalConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,9 +32,8 @@ export class GlobalConfigRepository<TGlobalConfig extends GlobalConfig = GlobalC
|
||||
* @param config - The global configuration data to create
|
||||
* @returns The created global configuration
|
||||
*/
|
||||
async create(config: TGlobalConfig): Promise<TGlobalConfig> {
|
||||
const document = await this.createDocument(config);
|
||||
return this.toDomain(document);
|
||||
async create(config: GlobalConfig): Promise<GlobalConfig> {
|
||||
return this.createDocument(config);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,10 +45,9 @@ export class GlobalConfigRepository<TGlobalConfig extends GlobalConfig = GlobalC
|
||||
* @returns The updated global configuration
|
||||
* @throws Error if no config exists
|
||||
*/
|
||||
async update(config: TGlobalConfig): Promise<TGlobalConfig> {
|
||||
async update(config: GlobalConfig): Promise<GlobalConfig> {
|
||||
// Update the first document in the collection (there should only be one)
|
||||
const document = await this.updateOne({}, config);
|
||||
return this.toDomain(document);
|
||||
return this.updateOne({}, config);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,10 +55,9 @@ export class GlobalConfigRepository<TGlobalConfig extends GlobalConfig = GlobalC
|
||||
*
|
||||
* @returns The global configuration or null if not found
|
||||
*/
|
||||
async get(): Promise<TGlobalConfig | null> {
|
||||
async get(): Promise<GlobalConfig | null> {
|
||||
// Get the first (and only) document from the collection
|
||||
const document = await this.findOne({});
|
||||
return document ? this.toDomain(document) : null;
|
||||
return this.findOne({});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { Require_id } from 'mongoose';
|
||||
import { MeetMigration, MigrationName, MigrationStatus } from '../models/migration.model.js';
|
||||
import { MeetMigrationDocument, MeetMigrationModel } from '../models/mongoose-schemas/migration.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
@ -10,14 +11,10 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
super(logger, MeetMigrationModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a MongoDB document into a domain MeetMigration object.
|
||||
*
|
||||
* @param document - The MongoDB document
|
||||
* @returns MeetMigration domain object
|
||||
*/
|
||||
protected toDomain(document: MeetMigrationDocument): MeetMigration {
|
||||
return document.toObject() as MeetMigration;
|
||||
protected toDomain(dbObject: Require_id<MeetMigrationDocument> & { __v: number }): MeetMigration {
|
||||
const { _id, __v, ...migration } = dbObject;
|
||||
(void _id, __v);
|
||||
return migration as MeetMigration;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,7 +31,7 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
|
||||
if (existingMigration) {
|
||||
// Update existing document to RUNNING status
|
||||
const document = await this.updateOne(
|
||||
return this.updateOne(
|
||||
{ name },
|
||||
{
|
||||
$set: {
|
||||
@ -47,16 +44,14 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
}
|
||||
}
|
||||
);
|
||||
return this.toDomain(document);
|
||||
}
|
||||
|
||||
// Create new migration document
|
||||
const document = await this.createDocument({
|
||||
return this.createDocument({
|
||||
name,
|
||||
status: MigrationStatus.RUNNING,
|
||||
startedAt: Date.now()
|
||||
});
|
||||
return this.toDomain(document);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,7 +63,7 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
* @returns The updated migration document
|
||||
*/
|
||||
async markAsCompleted(name: MigrationName, metadata?: Record<string, unknown>): Promise<MeetMigration> {
|
||||
const document = await this.updateOne(
|
||||
return this.updateOne(
|
||||
{ name },
|
||||
{
|
||||
$set: {
|
||||
@ -78,7 +73,6 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
}
|
||||
}
|
||||
);
|
||||
return this.toDomain(document);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +84,7 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
* @returns The updated migration document
|
||||
*/
|
||||
async markAsFailed(name: MigrationName, error: string): Promise<MeetMigration> {
|
||||
const document = await this.updateOne(
|
||||
return this.updateOne(
|
||||
{ name },
|
||||
{
|
||||
$set: {
|
||||
@ -100,7 +94,6 @@ export class MigrationRepository extends BaseRepository<MeetMigration, MeetMigra
|
||||
}
|
||||
}
|
||||
);
|
||||
return this.toDomain(document);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
SortOrder
|
||||
} from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { FilterQuery, Require_id } from 'mongoose';
|
||||
import { uid as secureUid } from 'uid/secure';
|
||||
import { MeetRecordingDocument, MeetRecordingModel } from '../models/mongoose-schemas/recording.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
@ -13,54 +14,36 @@ import { BaseRepository } from './base.repository.js';
|
||||
|
||||
/**
|
||||
* Repository for managing recording entities in MongoDB.
|
||||
* Handles CRUD operations and query filtering for recordings.
|
||||
* Provides CRUD operations and specialized queries for recording data.
|
||||
*/
|
||||
@injectable()
|
||||
export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetRecordingInfo> extends BaseRepository<
|
||||
TRecording,
|
||||
MeetRecordingDocument
|
||||
> {
|
||||
export class RecordingRepository extends BaseRepository<MeetRecordingInfo, MeetRecordingDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetRecordingModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Mongoose document to a domain object.
|
||||
* Removes access secrets before returning.
|
||||
*/
|
||||
protected toDomain(document: MeetRecordingDocument): TRecording {
|
||||
return document.toObject() as TRecording;
|
||||
protected toDomain(dbObject: Require_id<MeetRecordingDocument> & { __v: number }): MeetRecordingInfo {
|
||||
const { _id, __v, schemaVersion, accessSecrets, ...recording } = dbObject;
|
||||
(void _id, __v, schemaVersion, accessSecrets);
|
||||
return recording as MeetRecordingInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new recording document in the database.
|
||||
* Automatically generates access secrets if not provided.
|
||||
* Creates a new recording with generated access secrets.
|
||||
*
|
||||
* @param recording - The recording information to create (optionally includes accessSecrets)
|
||||
* @param recording - The recording information to create (excluding access secrets)
|
||||
* @returns The created recording (without access secrets)
|
||||
*/
|
||||
async create(recording: TRecording): Promise<TRecording> {
|
||||
// Check if recording already includes accessSecrets
|
||||
const hasAccessSecrets =
|
||||
'accessSecrets' in recording &&
|
||||
recording.accessSecrets &&
|
||||
typeof recording.accessSecrets === 'object' &&
|
||||
'public' in recording.accessSecrets &&
|
||||
'private' in recording.accessSecrets;
|
||||
|
||||
// Generate access secrets only if not provided
|
||||
const recordingDoc = {
|
||||
async create(recording: MeetRecordingInfo): Promise<MeetRecordingInfo> {
|
||||
// Generate access secrets
|
||||
const recordingDoc: Omit<MeetRecordingDocument, 'schemaVersion'> = {
|
||||
...recording,
|
||||
accessSecrets: hasAccessSecrets
|
||||
? recording.accessSecrets
|
||||
: {
|
||||
public: secureUid(10),
|
||||
private: secureUid(10)
|
||||
}
|
||||
accessSecrets: {
|
||||
public: secureUid(10),
|
||||
private: secureUid(10)
|
||||
}
|
||||
};
|
||||
|
||||
const result = await this.createDocument(recordingDoc);
|
||||
return this.toDomain(result);
|
||||
return this.createDocument(recordingDoc);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,9 +53,8 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @returns The updated recording (without access secrets)
|
||||
* @throws Error if recording not found
|
||||
*/
|
||||
async update(recording: TRecording): Promise<TRecording> {
|
||||
const document = await this.updateOne({ recordingId: recording.recordingId }, { $set: recording });
|
||||
return this.toDomain(document);
|
||||
async update(recording: MeetRecordingInfo): Promise<MeetRecordingInfo> {
|
||||
return this.updateOne({ recordingId: recording.recordingId }, { $set: recording });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,9 +64,8 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @param fields - Array of field names to include in the result
|
||||
* @returns The recording (without access secrets), or null if not found
|
||||
*/
|
||||
async findByRecordingId(recordingId: string, fields?: MeetRecordingField[]): Promise<TRecording | null> {
|
||||
const document = await this.findOne({ recordingId }, fields);
|
||||
return document ? this.toDomain(document) : null;
|
||||
async findByRecordingId(recordingId: string, fields?: MeetRecordingField[]): Promise<MeetRecordingInfo | null> {
|
||||
return this.findOne({ recordingId }, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +88,7 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @returns Object containing recordings array, pagination info, and optional next page token
|
||||
*/
|
||||
async find(options: MeetRecordingFilters & { roomIds?: string[] } = {}): Promise<{
|
||||
recordings: TRecording[];
|
||||
recordings: MeetRecordingInfo[];
|
||||
isTruncated: boolean;
|
||||
nextPageToken?: string;
|
||||
}> {
|
||||
@ -124,7 +105,7 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
} = options;
|
||||
|
||||
// Build base filter
|
||||
const filter: Record<string, unknown> = {};
|
||||
const filter: FilterQuery<MeetRecordingDocument> = {};
|
||||
|
||||
if (roomIds) {
|
||||
// Filter by multiple room IDs
|
||||
@ -171,7 +152,7 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @param roomId - The ID of the room
|
||||
* @returns Array of recordings for the specified room
|
||||
*/
|
||||
async findAllByRoomId(roomId: string): Promise<TRecording[]> {
|
||||
async findAllByRoomId(roomId: string): Promise<MeetRecordingInfo[]> {
|
||||
return await this.findAll({ roomId });
|
||||
}
|
||||
|
||||
@ -203,8 +184,8 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
*
|
||||
* @returns Array of active recordings
|
||||
*/
|
||||
async findActiveRecordings(): Promise<TRecording[]> {
|
||||
return await this.findAll({
|
||||
async findActiveRecordings(): Promise<MeetRecordingInfo[]> {
|
||||
return this.findAll({
|
||||
status: { $in: [MeetRecordingStatus.ACTIVE, MeetRecordingStatus.ENDING] }
|
||||
});
|
||||
}
|
||||
@ -216,7 +197,7 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @throws Error if the recording was not found or could not be deleted
|
||||
*/
|
||||
async deleteByRecordingId(recordingId: string): Promise<void> {
|
||||
await this.deleteOne({ recordingId });
|
||||
this.deleteOne({ recordingId });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,14 +207,14 @@ export class RecordingRepository<TRecording extends MeetRecordingInfo = MeetReco
|
||||
* @throws Error if any recording was not found or could not be deleted
|
||||
*/
|
||||
async deleteByRecordingIds(recordingIds: string[]): Promise<void> {
|
||||
await this.deleteMany({ recordingId: { $in: recordingIds } });
|
||||
this.deleteMany({ recordingId: { $in: recordingIds } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the total number of recordings.
|
||||
*/
|
||||
async countTotal(): Promise<number> {
|
||||
return await this.count();
|
||||
return this.count();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,30 +1,24 @@
|
||||
import { MeetRoomMember, MeetRoomMemberFilters, MeetRoomMemberPermissions, SortOrder } from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { FilterQuery, Require_id } from 'mongoose';
|
||||
import { MeetRoomMemberDocument, MeetRoomMemberModel } from '../models/mongoose-schemas/room-member.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
import { BaseRepository } from './base.repository.js';
|
||||
|
||||
/**
|
||||
* Repository for managing MeetRoomMember entities in MongoDB.
|
||||
* Handles the storage and retrieval of room members.
|
||||
* Provides CRUD operations and specialized queries for room member data.
|
||||
*/
|
||||
@injectable()
|
||||
export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomMember> extends BaseRepository<
|
||||
TRoomMember,
|
||||
MeetRoomMemberDocument
|
||||
> {
|
||||
export class RoomMemberRepository extends BaseRepository<MeetRoomMember, MeetRoomMemberDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetRoomMemberModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a MongoDB document into a domain room member object.
|
||||
*
|
||||
* @param document - The MongoDB document
|
||||
* @returns Room member with computed permissions
|
||||
*/
|
||||
protected toDomain(document: MeetRoomMemberDocument): TRoomMember {
|
||||
return document.toObject() as TRoomMember;
|
||||
protected toDomain(dbObject: Require_id<MeetRoomMemberDocument> & { __v: number }): MeetRoomMember {
|
||||
const { _id, __v, schemaVersion, ...member } = dbObject;
|
||||
(void _id, __v, schemaVersion);
|
||||
return member as MeetRoomMember;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,9 +27,8 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
* @param member - The room member data to add
|
||||
* @returns The created room member
|
||||
*/
|
||||
async create(member: TRoomMember): Promise<TRoomMember> {
|
||||
const document = await this.createDocument(member as TRoomMember);
|
||||
return this.toDomain(document);
|
||||
async create(member: MeetRoomMember): Promise<MeetRoomMember> {
|
||||
return this.createDocument(member);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,9 +38,8 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
* @returns The updated room member
|
||||
* @throws Error if room member not found
|
||||
*/
|
||||
async update(member: TRoomMember): Promise<TRoomMember> {
|
||||
const document = await this.updateOne({ roomId: member.roomId, memberId: member.memberId }, member);
|
||||
return this.toDomain(document);
|
||||
async update(member: MeetRoomMember): Promise<MeetRoomMember> {
|
||||
return this.updateOne({ roomId: member.roomId, memberId: member.memberId }, member);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,9 +49,8 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
* @param memberId - The ID of the member
|
||||
* @returns The room member or null if not found
|
||||
*/
|
||||
async findByRoomAndMemberId(roomId: string, memberId: string): Promise<TRoomMember | null> {
|
||||
const document = await this.findOne({ roomId, memberId });
|
||||
return document ? this.toDomain(document) : null;
|
||||
async findByRoomAndMemberId(roomId: string, memberId: string): Promise<MeetRoomMember | null> {
|
||||
return this.findOne({ roomId, memberId });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,8 +61,8 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
* @param fields - Array of field names to include in the result
|
||||
* @returns Array of found room members
|
||||
*/
|
||||
async findByRoomAndMemberIds(roomId: string, memberIds: string[], fields?: string[]): Promise<TRoomMember[]> {
|
||||
return await this.findAll({ roomId, memberId: { $in: memberIds } }, fields);
|
||||
async findByRoomAndMemberIds(roomId: string, memberIds: string[], fields?: string[]): Promise<MeetRoomMember[]> {
|
||||
return this.findAll({ roomId, memberId: { $in: memberIds } }, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +114,7 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
roomId: string,
|
||||
options: MeetRoomMemberFilters = {}
|
||||
): Promise<{
|
||||
members: TRoomMember[];
|
||||
members: MeetRoomMember[];
|
||||
isTruncated: boolean;
|
||||
nextPageToken?: string;
|
||||
}> {
|
||||
@ -137,7 +128,7 @@ export class RoomMemberRepository<TRoomMember extends MeetRoomMember = MeetRoomM
|
||||
} = options;
|
||||
|
||||
// Build base filter
|
||||
const filter: Record<string, unknown> = { roomId };
|
||||
const filter: FilterQuery<MeetRoomMemberDocument> = { roomId };
|
||||
|
||||
if (name) {
|
||||
filter.name = new RegExp(name, 'i');
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { MeetRoom, MeetRoomField, MeetRoomFilters, MeetRoomStatus, SortOrder } from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { FilterQuery, Require_id } from 'mongoose';
|
||||
import { MeetRoomDocument, MeetRoomModel } from '../models/mongoose-schemas/room.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
import { getBasePath } from '../utils/html-dynamic-base-path.utils.js';
|
||||
@ -9,24 +10,24 @@ import { BaseRepository } from './base.repository.js';
|
||||
/**
|
||||
* Repository for managing MeetRoom entities in MongoDB.
|
||||
* Provides CRUD operations and specialized queries for room data.
|
||||
*
|
||||
* @template TRoom - The domain type extending MeetRoom (default: MeetRoom)
|
||||
*/
|
||||
@injectable()
|
||||
export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepository<TRoom, MeetRoomDocument> {
|
||||
export class RoomRepository extends BaseRepository<MeetRoom, MeetRoomDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetRoomModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a MongoDB document into a domain room object.
|
||||
* Enriches URLs with the base URL.
|
||||
* Transforms a persisted MeetRoom document into a domain MeetRoom object.
|
||||
* Enriches access URLs with the base URL.
|
||||
*
|
||||
* @param document - The MongoDB document
|
||||
* @param dbObject - The MongoDB document representing a room
|
||||
* @returns Room with complete URLs
|
||||
*/
|
||||
protected toDomain(document: MeetRoomDocument): TRoom {
|
||||
return this.enrichRoomWithBaseUrls(document);
|
||||
protected toDomain(dbObject: Require_id<MeetRoomDocument> & { __v: number }): MeetRoom {
|
||||
const { _id, __v, schemaVersion, ...room } = dbObject;
|
||||
(void _id, __v, schemaVersion);
|
||||
return this.enrichRoomWithBaseUrls(room as MeetRoom);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -36,10 +37,9 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param room - The room data to create
|
||||
* @returns The created room with enriched URLs
|
||||
*/
|
||||
async create(room: TRoom): Promise<TRoom> {
|
||||
async create(room: MeetRoom): Promise<MeetRoom> {
|
||||
const normalizedRoom = this.normalizeRoomForStorage(room);
|
||||
const document = await this.createDocument(normalizedRoom);
|
||||
return this.enrichRoomWithBaseUrls(document);
|
||||
return this.createDocument(normalizedRoom);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,10 +52,9 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
*
|
||||
* TODO: This method should be renamed to replace or updateFull to better reflect that it replaces the entire document
|
||||
*/
|
||||
async update(room: TRoom): Promise<TRoom> {
|
||||
async update(room: MeetRoom): Promise<MeetRoom> {
|
||||
const normalizedRoom = this.normalizeRoomForStorage(room);
|
||||
const document = await this.updateOne({ roomId: room.roomId }, normalizedRoom);
|
||||
return this.enrichRoomWithBaseUrls(document);
|
||||
return this.updateOne({ roomId: room.roomId }, normalizedRoom);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +63,7 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param roomId
|
||||
* @param fieldsToUpdate
|
||||
*/
|
||||
async updatePartial(roomId: string, fieldsToUpdate: Partial<TRoom>): Promise<void> {
|
||||
async updatePartial(roomId: string, fieldsToUpdate: Partial<MeetRoom>): Promise<void> {
|
||||
await this.updateOne({ roomId }, fieldsToUpdate);
|
||||
}
|
||||
|
||||
@ -76,9 +75,8 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param fields - Array of field names to include in the result
|
||||
* @returns The room or null if not found
|
||||
*/
|
||||
async findByRoomId(roomId: string, fields?: MeetRoomField[]): Promise<TRoom | null> {
|
||||
const document = await this.findOne({ roomId }, fields);
|
||||
return document ? this.enrichRoomWithBaseUrls(document) : null;
|
||||
async findByRoomId(roomId: string, fields?: MeetRoomField[]): Promise<MeetRoom | null> {
|
||||
return this.findOne({ roomId }, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,8 +87,8 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param fields - Array of field names to include in the result
|
||||
* @returns Array of rooms owned by the user
|
||||
*/
|
||||
async findByOwner(owner: string, fields?: MeetRoomField[]): Promise<TRoom[]> {
|
||||
return await this.findAll({ owner }, fields);
|
||||
async findByOwner(owner: string, fields?: MeetRoomField[]): Promise<MeetRoom[]> {
|
||||
return this.findAll({ owner }, fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +111,7 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @returns Object containing rooms array, pagination info, and optional next page token
|
||||
*/
|
||||
async find(options: MeetRoomFilters & { owner?: string; roomIds?: string[] } = {}): Promise<{
|
||||
rooms: TRoom[];
|
||||
rooms: MeetRoom[];
|
||||
isTruncated: boolean;
|
||||
nextPageToken?: string;
|
||||
}> {
|
||||
@ -130,7 +128,7 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
} = options;
|
||||
|
||||
// Build base filter
|
||||
const filter: Record<string, unknown> = {};
|
||||
const filter: FilterQuery<MeetRoomDocument> = {};
|
||||
|
||||
// Handle owner and roomIds with $or when both are present
|
||||
if (owner && roomIds) {
|
||||
@ -174,11 +172,11 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
*
|
||||
* @returns Array of expired rooms with enriched URLs
|
||||
*/
|
||||
async findExpiredRooms(): Promise<TRoom[]> {
|
||||
async findExpiredRooms(): Promise<MeetRoom[]> {
|
||||
const now = Date.now();
|
||||
|
||||
// Find all rooms where autoDeletionDate exists and is less than now
|
||||
return await this.findAll({
|
||||
return this.findAll({
|
||||
autoDeletionDate: { $exists: true, $lt: now }
|
||||
});
|
||||
}
|
||||
@ -189,8 +187,8 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
*
|
||||
* @returns Array of active rooms with enriched URLs
|
||||
*/
|
||||
async findActiveRooms(): Promise<TRoom[]> {
|
||||
return await this.findAll({
|
||||
async findActiveRooms(): Promise<MeetRoom[]> {
|
||||
return this.findAll({
|
||||
status: MeetRoomStatus.ACTIVE_MEETING
|
||||
});
|
||||
}
|
||||
@ -219,14 +217,14 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* Counts the total number of rooms.
|
||||
*/
|
||||
async countTotal(): Promise<number> {
|
||||
return await this.count();
|
||||
return this.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of rooms with active meetings.
|
||||
*/
|
||||
async countActiveRooms(): Promise<number> {
|
||||
return await this.count({ status: MeetRoomStatus.ACTIVE_MEETING });
|
||||
return this.count({ status: MeetRoomStatus.ACTIVE_MEETING });
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
@ -240,7 +238,7 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param room - The room data to normalize
|
||||
* @returns Normalized room data
|
||||
*/
|
||||
private normalizeRoomForStorage(room: TRoom): TRoom {
|
||||
private normalizeRoomForStorage(room: MeetRoom): MeetRoom {
|
||||
return {
|
||||
...room,
|
||||
accessUrl: this.extractPathFromUrl(room.accessUrl),
|
||||
@ -307,9 +305,8 @@ export class RoomRepository<TRoom extends MeetRoom = MeetRoom> extends BaseRepos
|
||||
* @param document - The MongoDB document
|
||||
* @returns Room data with complete URLs
|
||||
*/
|
||||
private enrichRoomWithBaseUrls(document: MeetRoomDocument): TRoom {
|
||||
private enrichRoomWithBaseUrls(room: MeetRoom): MeetRoom {
|
||||
const baseUrl = getBaseUrl();
|
||||
const room = document.toObject() as TRoom;
|
||||
|
||||
return {
|
||||
...room,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { MeetUser, MeetUserFilters, SortOrder } from '@openvidu-meet/typings';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { FilterQuery, Require_id } from 'mongoose';
|
||||
import { MeetUserDocument, MeetUserModel } from '../models/mongoose-schemas/user.schema.js';
|
||||
import { LoggerService } from '../services/logger.service.js';
|
||||
import { BaseRepository } from './base.repository.js';
|
||||
@ -7,23 +8,17 @@ import { BaseRepository } from './base.repository.js';
|
||||
/**
|
||||
* Repository for managing MeetUser entities in MongoDB.
|
||||
* Provides CRUD operations and specialized queries for user data.
|
||||
*
|
||||
* @template TUser - The domain type extending MeetUser (default: MeetUser)
|
||||
*/
|
||||
@injectable()
|
||||
export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepository<TUser, MeetUserDocument> {
|
||||
export class UserRepository extends BaseRepository<MeetUser, MeetUserDocument> {
|
||||
constructor(@inject(LoggerService) logger: LoggerService) {
|
||||
super(logger, MeetUserModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a MongoDB document into a domain user object.
|
||||
*
|
||||
* @param document - The MongoDB document
|
||||
* @returns User domain object
|
||||
*/
|
||||
protected toDomain(document: MeetUserDocument): TUser {
|
||||
return document.toObject() as TUser;
|
||||
protected toDomain(dbObject: Require_id<MeetUserDocument> & { __v: number }): MeetUser {
|
||||
const { _id, __v, schemaVersion, ...user } = dbObject;
|
||||
(void _id, __v, schemaVersion);
|
||||
return user as MeetUser;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,9 +27,8 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
* @param user - The user data to create
|
||||
* @returns The created user
|
||||
*/
|
||||
async create(user: TUser): Promise<TUser> {
|
||||
const document = await this.createDocument(user);
|
||||
return this.toDomain(document);
|
||||
async create(user: MeetUser): Promise<MeetUser> {
|
||||
return this.createDocument(user);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,9 +38,8 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
* @returns The updated user
|
||||
* @throws Error if user not found
|
||||
*/
|
||||
async update(user: TUser): Promise<TUser> {
|
||||
const document = await this.updateOne({ userId: user.userId }, user);
|
||||
return this.toDomain(document);
|
||||
async update(user: MeetUser): Promise<MeetUser> {
|
||||
return this.updateOne({ userId: user.userId }, user);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,9 +48,8 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
* @param userId - The unique user identifier
|
||||
* @returns The user or null if not found
|
||||
*/
|
||||
async findByUserId(userId: string): Promise<TUser | null> {
|
||||
const document = await this.findOne({ userId });
|
||||
return document ? this.toDomain(document) : null;
|
||||
async findByUserId(userId: string): Promise<MeetUser | null> {
|
||||
return this.findOne({ userId });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +58,7 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
* @param userIds - Array of user identifiers
|
||||
* @returns Array of found users
|
||||
*/
|
||||
async findByUserIds(userIds: string[]): Promise<TUser[]> {
|
||||
async findByUserIds(userIds: string[]): Promise<MeetUser[]> {
|
||||
return await this.findAll({ userId: { $in: userIds } });
|
||||
}
|
||||
|
||||
@ -84,7 +76,7 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
* @returns Object containing users array, pagination info, and optional next page token
|
||||
*/
|
||||
async find(options: MeetUserFilters = {}): Promise<{
|
||||
users: TUser[];
|
||||
users: MeetUser[];
|
||||
isTruncated: boolean;
|
||||
nextPageToken?: string;
|
||||
}> {
|
||||
@ -99,7 +91,7 @@ export class UserRepository<TUser extends MeetUser = MeetUser> extends BaseRepos
|
||||
} = options;
|
||||
|
||||
// Build base filter
|
||||
const filter: Record<string, unknown> = {};
|
||||
const filter: FilterQuery<MeetUserDocument> = {};
|
||||
|
||||
if (userId && name) {
|
||||
// Both defined: OR filter with regex userId match and regex name match
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user