refactor: eslint and prettier conflict will be resolved and formatted

This commit is contained in:
Enes Köksal
2026-04-23 17:05:43 +03:00
parent 385b61f29b
commit 3cfea40fbd
219 changed files with 16638 additions and 13663 deletions
+31 -11
View File
@@ -21,7 +21,8 @@ type BunnyVideo = {
function getBunnyConfig(): BunnyConfig {
const apiKey = process.env.BUNNY_STREAM_API_KEY;
const libraryId = process.env.BUNNY_STREAM_LIBRARY_ID || process.env.NEXT_PUBLIC_BUNNY_STREAM_LIBRARY_ID;
const libraryId =
process.env.BUNNY_STREAM_LIBRARY_ID || process.env.NEXT_PUBLIC_BUNNY_STREAM_LIBRARY_ID;
if (!apiKey || !libraryId) {
throw new Error('Missing BUNNY_STREAM_API_KEY or BUNNY_STREAM_LIBRARY_ID.');
@@ -72,7 +73,10 @@ function parseUploadedAt(item: unknown): Date | null {
return null;
}
async function fetchBunnyPage(config: BunnyConfig, page: number): Promise<{ items: unknown[]; totalItems: number | null }> {
async function fetchBunnyPage(
config: BunnyConfig,
page: number
): Promise<{ items: unknown[]; totalItems: number | null }> {
const response = await fetch(
`${BUNNY_API_BASE}/library/${config.libraryId}/videos?page=${page}&itemsPerPage=${ITEMS_PER_PAGE}`,
{
@@ -95,16 +99,23 @@ async function fetchBunnyPage(config: BunnyConfig, page: number): Promise<{ item
const items = Array.isArray(record.items)
? record.items
: (Array.isArray(record.Items) ? record.Items : []);
: Array.isArray(record.Items)
? record.Items
: [];
const totalItems = typeof record.totalItems === 'number'
? record.totalItems
: (typeof record.TotalItems === 'number' ? record.TotalItems : null);
const totalItems =
typeof record.totalItems === 'number'
? record.totalItems
: typeof record.TotalItems === 'number'
? record.TotalItems
: null;
return { items, totalItems };
}
async function listBunnyVideos(config: BunnyConfig): Promise<{ videos: BunnyVideo[]; scanned: number; skippedInvalid: number }> {
async function listBunnyVideos(
config: BunnyConfig
): Promise<{ videos: BunnyVideo[]; scanned: number; skippedInvalid: number }> {
const videos: BunnyVideo[] = [];
let scanned = 0;
let skippedInvalid = 0;
@@ -171,7 +182,10 @@ async function findReferencedVideoIds(videoIds: string[]): Promise<Set<string>>
return referenced;
}
async function deleteBunnyVideo(config: BunnyConfig, videoId: string): Promise<'deleted' | 'already_missing'> {
async function deleteBunnyVideo(
config: BunnyConfig,
videoId: string
): Promise<'deleted' | 'already_missing'> {
const response = await fetch(
`${BUNNY_API_BASE}/library/${config.libraryId}/videos/${encodeURIComponent(videoId)}`,
{
@@ -186,7 +200,9 @@ async function deleteBunnyVideo(config: BunnyConfig, videoId: string): Promise<'
if (response.ok) return 'deleted';
const body = await response.text().catch(() => '');
throw new Error(`Bunny delete API failed for ${videoId} (${response.status}): ${body.slice(0, 300)}`);
throw new Error(
`Bunny delete API failed for ${videoId} (${response.status}): ${body.slice(0, 300)}`
);
}
async function main() {
@@ -200,8 +216,12 @@ async function main() {
console.log(`[bunny-orphan-cleanup] Grace period: ${graceHours}h`);
const expiredBillingCleanup = await cleanupExpiredBillingWorkspaces({ dryRun });
console.log(`[bunny-orphan-cleanup] Expired owner workspaces scanned: ${expiredBillingCleanup.scanned}`);
console.log(`[bunny-orphan-cleanup] Expired owner workspaces deleted: ${expiredBillingCleanup.deleted}`);
console.log(
`[bunny-orphan-cleanup] Expired owner workspaces scanned: ${expiredBillingCleanup.scanned}`
);
console.log(
`[bunny-orphan-cleanup] Expired owner workspaces deleted: ${expiredBillingCleanup.deleted}`
);
const { videos, scanned, skippedInvalid } = await listBunnyVideos(config);
const eligible = videos.filter((video) => video.uploadedAt.getTime() <= cutoff);
+6 -2
View File
@@ -104,11 +104,15 @@ async function main() {
const failedMigrations = migrationRows.filter((row) => !row.finished_at && !row.rolled_back_at);
const shouldBootstrapFreshSchema = !hasCoreTables;
console.log(`Detected public tables: ${appTables.length > 0 ? appTables.join(', ') : '(none)'}`);
console.log(
`Detected public tables: ${appTables.length > 0 ? appTables.join(', ') : '(none)'}`
);
if (shouldBootstrapFreshSchema) {
if (failedMigrations.length > 0) {
console.log('Detected failed migration state on a fresh database. Marking failed migrations as rolled back.');
console.log(
'Detected failed migration state on a fresh database. Marking failed migrations as rolled back.'
);
for (const migration of failedMigrations) {
await runPrisma(['migrate', 'resolve', '--rolled-back', migration.migration_name]);
}
+20 -18
View File
@@ -19,26 +19,28 @@ async function getExpiredWorkspaceTargets(): Promise<ExpiredWorkspaceTarget[]> {
return [];
}
return db.workspace.findMany({
where: {
ownerId: { in: expiredOwners.map((owner) => owner.id) },
},
select: {
id: true,
ownerId: true,
owner: {
select: {
email: true,
return db.workspace
.findMany({
where: {
ownerId: { in: expiredOwners.map((owner) => owner.id) },
},
select: {
id: true,
ownerId: true,
owner: {
select: {
email: true,
},
},
},
},
}).then((workspaces) =>
workspaces.map((workspace) => ({
id: workspace.id,
ownerId: workspace.ownerId,
ownerEmail: workspace.owner.email,
}))
);
})
.then((workspaces) =>
workspaces.map((workspace) => ({
id: workspace.id,
ownerId: workspace.ownerId,
ownerEmail: workspace.owner.email,
}))
);
}
export async function cleanupExpiredBillingWorkspaces(options?: { dryRun?: boolean }) {
+30 -12
View File
@@ -1,4 +1,8 @@
import { DeleteObjectCommand, ListObjectsV2Command, type ListObjectsV2CommandInput } from '@aws-sdk/client-s3';
import {
DeleteObjectCommand,
ListObjectsV2Command,
type ListObjectsV2CommandInput,
} from '@aws-sdk/client-s3';
import { db, disconnectDb } from '../lib/db';
import { r2Client, R2_BUCKET_NAME } from '../lib/r2';
import { cleanupExpiredBillingWorkspaces } from './expired-billing-cleanup';
@@ -14,7 +18,10 @@ type CleanupCandidate = {
};
type UserFeedbackScreenshotDelegate = {
findMany: (args: { where: { url: { in: string[] } }; select: { url: true } }) => Promise<Array<{ url: string }>>;
findMany: (args: {
where: { url: { in: string[] } };
select: { url: true };
}) => Promise<Array<{ url: string }>>;
};
function keyToProxyUrl(key: string): string | null {
@@ -37,7 +44,10 @@ function chunk<T>(items: T[], size: number): T[][] {
return out;
}
async function listCleanupCandidates(): Promise<{ candidates: CleanupCandidate[]; scanned: number }> {
async function listCleanupCandidates(): Promise<{
candidates: CleanupCandidate[];
scanned: number;
}> {
const candidates: CleanupCandidate[] = [];
const cutoff = Date.now() - UNATTACHED_UPLOAD_TTL_MS;
let scanned = 0;
@@ -76,9 +86,11 @@ async function listCleanupCandidates(): Promise<{ candidates: CleanupCandidate[]
async function findReferencedUrls(urls: string[]): Promise<Set<string>> {
const referenced = new Set<string>();
const userFeedbackScreenshotDelegate = (db as unknown as {
userFeedbackScreenshot?: UserFeedbackScreenshotDelegate;
}).userFeedbackScreenshot;
const userFeedbackScreenshotDelegate = (
db as unknown as {
userFeedbackScreenshot?: UserFeedbackScreenshotDelegate;
}
).userFeedbackScreenshot;
for (const group of chunk(urls, CHUNK_SIZE)) {
const [commentRows, feedbackRows, feedbackAttachmentRows, assetRows] = await Promise.all([
@@ -97,9 +109,9 @@ async function findReferencedUrls(urls: string[]): Promise<Set<string>> {
}),
userFeedbackScreenshotDelegate
? userFeedbackScreenshotDelegate.findMany({
where: { url: { in: group } },
select: { url: true },
})
where: { url: { in: group } },
select: { url: true },
})
: Promise.resolve([] as Array<{ url: string }>),
db.videoAsset.findMany({
where: { sourceUrl: { in: group } },
@@ -130,11 +142,17 @@ async function main() {
console.log(`[r2-orphan-cleanup] Starting (${dryRun ? 'dry-run' : 'delete mode'})`);
const expiredBillingCleanup = await cleanupExpiredBillingWorkspaces({ dryRun });
console.log(`[r2-orphan-cleanup] Expired owner workspaces scanned: ${expiredBillingCleanup.scanned}`);
console.log(`[r2-orphan-cleanup] Expired owner workspaces deleted: ${expiredBillingCleanup.deleted}`);
console.log(
`[r2-orphan-cleanup] Expired owner workspaces scanned: ${expiredBillingCleanup.scanned}`
);
console.log(
`[r2-orphan-cleanup] Expired owner workspaces deleted: ${expiredBillingCleanup.deleted}`
);
const { candidates, scanned } = await listCleanupCandidates();
console.log(`[r2-orphan-cleanup] Scanned: ${scanned}, eligible (old enough): ${candidates.length}`);
console.log(
`[r2-orphan-cleanup] Scanned: ${scanned}, eligible (old enough): ${candidates.length}`
);
if (candidates.length === 0) {
console.log('[r2-orphan-cleanup] No eligible objects found');
+3 -1
View File
@@ -2,7 +2,9 @@ import 'dotenv/config';
import { ensureR2BucketExists, R2_BUCKET_NAME } from '@/lib/r2';
import { logError } from '@/lib/logger';
const shouldCreateBucket = /^(1|true|yes|on)$/i.test(process.env.SELF_HOSTED_AUTO_CREATE_BUCKET ?? '');
const shouldCreateBucket = /^(1|true|yes|on)$/i.test(
process.env.SELF_HOSTED_AUTO_CREATE_BUCKET ?? ''
);
async function main() {
if (!shouldCreateBucket) {