mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
refactor: eslint and prettier conflict will be resolved and formatted
This commit is contained in:
@@ -75,28 +75,40 @@ export async function POST(request: NextRequest, { params }: RouteParams) {
|
||||
include: {
|
||||
video: {
|
||||
include: {
|
||||
project: { select: { id: true, name: true, ownerId: true, workspaceId: true, visibility: true } },
|
||||
project: {
|
||||
select: { id: true, name: true, ownerId: true, workspaceId: true, visibility: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!version) return apiErrors.notFound('Version');
|
||||
|
||||
const access = await checkProjectAccess(version.video.project, session.user.id, { intent: 'manage' });
|
||||
const access = await checkProjectAccess(version.video.project, session.user.id, {
|
||||
intent: 'manage',
|
||||
});
|
||||
if (!access.canEdit) return apiErrors.forbidden('Access denied');
|
||||
|
||||
const body = await request.json().catch(() => ({})) as { approverIds?: unknown; message?: unknown };
|
||||
const body = (await request.json().catch(() => ({}))) as {
|
||||
approverIds?: unknown;
|
||||
message?: unknown;
|
||||
};
|
||||
const message = typeof body.message === 'string' ? body.message.trim() : '';
|
||||
if (message.length > 2000) {
|
||||
return apiErrors.badRequest('Message must be 2000 characters or fewer');
|
||||
}
|
||||
|
||||
const rawApproverIds = Array.isArray(body.approverIds) ? body.approverIds : [];
|
||||
const approverIds = Array.from(new Set(
|
||||
rawApproverIds
|
||||
.filter((approverId): approverId is string => typeof approverId === 'string' && approverId.trim().length > 0)
|
||||
.map((approverId) => approverId.trim())
|
||||
));
|
||||
const approverIds = Array.from(
|
||||
new Set(
|
||||
rawApproverIds
|
||||
.filter(
|
||||
(approverId): approverId is string =>
|
||||
typeof approverId === 'string' && approverId.trim().length > 0
|
||||
)
|
||||
.map((approverId) => approverId.trim())
|
||||
)
|
||||
);
|
||||
|
||||
if (approverIds.length === 0) {
|
||||
return apiErrors.badRequest('At least one approver is required');
|
||||
@@ -114,43 +126,46 @@ export async function POST(request: NextRequest, { params }: RouteParams) {
|
||||
return apiErrors.badRequest('One or more approvers are not eligible for this project');
|
||||
}
|
||||
|
||||
const created = await db.$transaction(async (tx) => {
|
||||
const existingPending = await tx.approvalRequest.findFirst({
|
||||
where: { versionId, status: 'PENDING' },
|
||||
select: { id: true },
|
||||
});
|
||||
if (existingPending) {
|
||||
throw new Error('__PENDING_REQUEST_EXISTS__');
|
||||
}
|
||||
const created = await db.$transaction(
|
||||
async (tx) => {
|
||||
const existingPending = await tx.approvalRequest.findFirst({
|
||||
where: { versionId, status: 'PENDING' },
|
||||
select: { id: true },
|
||||
});
|
||||
if (existingPending) {
|
||||
throw new Error('__PENDING_REQUEST_EXISTS__');
|
||||
}
|
||||
|
||||
return tx.approvalRequest.create({
|
||||
data: {
|
||||
versionId,
|
||||
requestedById: session.user.id,
|
||||
message: message || null,
|
||||
decisions: {
|
||||
createMany: {
|
||||
data: approverIds.map((approverId) => ({
|
||||
approverId,
|
||||
status: 'PENDING',
|
||||
})),
|
||||
return tx.approvalRequest.create({
|
||||
data: {
|
||||
versionId,
|
||||
requestedById: session.user.id,
|
||||
message: message || null,
|
||||
decisions: {
|
||||
createMany: {
|
||||
data: approverIds.map((approverId) => ({
|
||||
approverId,
|
||||
status: 'PENDING',
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
include: {
|
||||
requestedBy: { select: { id: true, name: true, email: true, image: true } },
|
||||
canceledBy: { select: { id: true, name: true, email: true, image: true } },
|
||||
decisions: {
|
||||
orderBy: { createdAt: 'asc' },
|
||||
include: {
|
||||
approver: { select: { id: true, name: true, email: true, image: true } },
|
||||
include: {
|
||||
requestedBy: { select: { id: true, name: true, email: true, image: true } },
|
||||
canceledBy: { select: { id: true, name: true, email: true, image: true } },
|
||||
decisions: {
|
||||
orderBy: { createdAt: 'asc' },
|
||||
include: {
|
||||
approver: { select: { id: true, name: true, email: true, image: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}, {
|
||||
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
|
||||
});
|
||||
});
|
||||
},
|
||||
{
|
||||
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
|
||||
}
|
||||
);
|
||||
|
||||
const requesterName = session.user.name || 'A team member';
|
||||
const versionLabel = version.versionLabel || `Version ${version.versionNumber}`;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,10 @@ function buildBunnySourceCacheKey(
|
||||
return `${videoId}:${requestedQuality ?? 'none'}:${sourcePreference}`;
|
||||
}
|
||||
|
||||
function getCachedBunnyDownloadSource(cacheKey: string, now: number): BunnyDownloadSource | null | undefined {
|
||||
function getCachedBunnyDownloadSource(
|
||||
cacheKey: string,
|
||||
now: number
|
||||
): BunnyDownloadSource | null | undefined {
|
||||
const cached = bunnyDownloadSourceCache.get(cacheKey);
|
||||
if (!cached) return undefined;
|
||||
|
||||
@@ -60,7 +63,11 @@ function getCachedBunnyDownloadSource(cacheKey: string, now: number): BunnyDownl
|
||||
return cached.source;
|
||||
}
|
||||
|
||||
function setCachedBunnyDownloadSource(cacheKey: string, source: BunnyDownloadSource | null, now: number): void {
|
||||
function setCachedBunnyDownloadSource(
|
||||
cacheKey: string,
|
||||
source: BunnyDownloadSource | null,
|
||||
now: number
|
||||
): void {
|
||||
if (bunnyDownloadSourceCache.size >= BUNNY_SOURCE_CACHE_MAX_ENTRIES) {
|
||||
// Evict the oldest entry (Maps preserve insertion order)
|
||||
const firstKey = bunnyDownloadSourceCache.keys().next().value;
|
||||
@@ -146,7 +153,10 @@ async function resolveBunnyOriginalSource(videoId: string): Promise<BunnyDownloa
|
||||
return null;
|
||||
}
|
||||
|
||||
async function resolveBunnyCompressedSource(videoId: string, requestedQuality: number | null): Promise<BunnyDownloadSource> {
|
||||
async function resolveBunnyCompressedSource(
|
||||
videoId: string,
|
||||
requestedQuality: number | null
|
||||
): Promise<BunnyDownloadSource> {
|
||||
const hostname = resolveBunnyCdnHostname();
|
||||
if (!hostname) {
|
||||
return {
|
||||
@@ -156,7 +166,11 @@ async function resolveBunnyCompressedSource(videoId: string, requestedQuality: n
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof requestedQuality === 'number' && Number.isFinite(requestedQuality) && requestedQuality > 0) {
|
||||
if (
|
||||
typeof requestedQuality === 'number' &&
|
||||
Number.isFinite(requestedQuality) &&
|
||||
requestedQuality > 0
|
||||
) {
|
||||
const requestedUrl = `https://${hostname}/${videoId}/play_${requestedQuality}p.mp4`;
|
||||
if (await isRemoteFileAvailable(requestedUrl)) {
|
||||
return {
|
||||
@@ -243,9 +257,11 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
||||
const rawQuality = searchParams.get('quality');
|
||||
const sourceParam = searchParams.get('source');
|
||||
const sourcePreference: BunnyDownloadSourcePreference =
|
||||
sourceParam === null ? 'auto' : sourceParam === 'original' || sourceParam === 'compressed'
|
||||
? sourceParam
|
||||
: 'auto';
|
||||
sourceParam === null
|
||||
? 'auto'
|
||||
: sourceParam === 'original' || sourceParam === 'compressed'
|
||||
? sourceParam
|
||||
: 'auto';
|
||||
|
||||
const version = await db.videoVersion.findUnique({
|
||||
where: { id: versionId },
|
||||
@@ -275,13 +291,19 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
||||
const shareSession = getShareSessionFromRequest(request, version.video.id);
|
||||
const shareAccess = shareSession
|
||||
? await validateShareLinkAccess({
|
||||
token: shareSession.token,
|
||||
projectId: version.video.projectId,
|
||||
videoId: version.video.id,
|
||||
requiredPermission: 'VIEW',
|
||||
passwordVerified: shareSession.passwordVerified,
|
||||
})
|
||||
: { hasAccess: false, canComment: false, canDownload: false, allowGuests: false, requiresPassword: false };
|
||||
token: shareSession.token,
|
||||
projectId: version.video.projectId,
|
||||
videoId: version.video.id,
|
||||
requiredPermission: 'VIEW',
|
||||
passwordVerified: shareSession.passwordVerified,
|
||||
})
|
||||
: {
|
||||
hasAccess: false,
|
||||
canComment: false,
|
||||
canDownload: false,
|
||||
allowGuests: false,
|
||||
requiresPassword: false,
|
||||
};
|
||||
const canDownloadViaShareLink = shareAccess.hasAccess && shareAccess.canDownload;
|
||||
if (!access.hasAccess && !canDownloadViaShareLink) {
|
||||
return apiErrors.forbidden('Access denied');
|
||||
@@ -299,7 +321,9 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
||||
rawQuality !== null &&
|
||||
(!Number.isFinite(requestedQuality) || !BUNNY_ALLOWED_QUALITIES.has(requestedQuality))
|
||||
) {
|
||||
return apiErrors.badRequest('Invalid quality. Allowed values: 2160, 1440, 1080, 720, 480, 360, 240');
|
||||
return apiErrors.badRequest(
|
||||
'Invalid quality. Allowed values: 2160, 1440, 1080, 720, 480, 360, 240'
|
||||
);
|
||||
}
|
||||
|
||||
if (rawQuality !== null && sourcePreference === 'original') {
|
||||
@@ -349,7 +373,10 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
||||
workspaceId: version.video.project.workspace.id,
|
||||
billedUserId: version.video.project.workspace.ownerId,
|
||||
downloaderUserId: session?.user?.id ?? null,
|
||||
source: source.sourceType === 'original' ? DownloadEgressSource.ORIGINAL : DownloadEgressSource.COMPRESSED,
|
||||
source:
|
||||
source.sourceType === 'original'
|
||||
? DownloadEgressSource.ORIGINAL
|
||||
: DownloadEgressSource.COMPRESSED,
|
||||
quality: source.quality,
|
||||
estimatedBytes,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user