chore: fix lint errors — duplicate import, unused imports, formatting
Deploy FileDrop / deploy (push) Successful in 45s
Deploy FileDrop / deploy (push) Successful in 45s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,17 @@
|
||||
import {
|
||||
type AuthSession,
|
||||
createLoginUseCase,
|
||||
createLogoutUseCase,
|
||||
createMeUseCase,
|
||||
} from '../../../application/use-cases/authenticate';
|
||||
import { config } from '../../../config/index';
|
||||
import {
|
||||
checkBearerToken,
|
||||
clearSessionCookie,
|
||||
createSessionCookie,
|
||||
getAuthSession,
|
||||
isAuthEnabled,
|
||||
checkBearerToken,
|
||||
} from '../../../utils/auth';
|
||||
import {
|
||||
createLoginUseCase,
|
||||
createLogoutUseCase,
|
||||
createMeUseCase,
|
||||
type AuthSession,
|
||||
} from '../../../application/use-cases/authenticate';
|
||||
|
||||
/**
|
||||
* Helper that builds a JSON Response with optional extra headers.
|
||||
@@ -148,4 +148,4 @@ export const handleMe = async (req: Request): Promise<Response> => {
|
||||
username: result.username,
|
||||
expiresAt: result.expiresAt,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { config } from '../../../config/index';
|
||||
import { fileInfoCache } from '../../../infrastructure/cache/index';
|
||||
import { createChunkedObjectResponse } from '../../../utils/chunked-storage';
|
||||
import { cleanupTempFile, formatCreatedAt, getErrorMessage } from '../../../shared/utils/file';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { cleanupTempFile, formatCreatedAt, getErrorMessage } from '../../../shared/utils/file';
|
||||
import { createChunkedObjectResponse } from '../../../utils/chunked-storage';
|
||||
import { getFileInfo, type TelegramFileInfo } from '../../../utils/telegram';
|
||||
import { locateZipEntry } from '../../../utils/zip';
|
||||
|
||||
@@ -25,7 +24,7 @@ type RequestWithParams = Request & {
|
||||
* @param value - The string value to wrap.
|
||||
* @returns The value as a single-element tuple.
|
||||
*/
|
||||
const asArray = (value: string): string[] => [value];
|
||||
const _asArray = (value: string): string[] => [value];
|
||||
|
||||
/**
|
||||
* Resolves Telegram file metadata for a given file ID, using the in-memory
|
||||
@@ -35,7 +34,10 @@ const asArray = (value: string): string[] => [value];
|
||||
* @param publicId - The public file ID (used for logging).
|
||||
* @returns The resolved Telegram file info.
|
||||
*/
|
||||
const getTelegramFileInfo = async (telegramFileId: string, publicId: string): Promise<TelegramFileInfo> => {
|
||||
const getTelegramFileInfo = async (
|
||||
telegramFileId: string,
|
||||
publicId: string,
|
||||
): Promise<TelegramFileInfo> => {
|
||||
const cacheKey = `file_info_${telegramFileId}`;
|
||||
const cached = fileInfoCache.get(cacheKey) as TelegramFileInfo | null;
|
||||
|
||||
@@ -212,4 +214,4 @@ export const handleFileInfo = async (req: RequestWithParams): Promise<Response>
|
||||
logger.error('File info error', { publicId, error: getErrorMessage(error) });
|
||||
return fail(500, 'Server error');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { db } from '../../../infrastructure/persistence/drizzle/index';
|
||||
import { getErrorMessage } from '../../../shared/utils/file';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { getErrorMessage } from '../../../shared/utils/file';
|
||||
|
||||
/**
|
||||
* Handles the health-check endpoint.
|
||||
@@ -22,4 +22,4 @@ export const handleHealth = async (_req: Request): Promise<Response> => {
|
||||
logger.error('Health check failed', { error: message });
|
||||
return Response.json({ status: 'error', error: message }, { status: 500 });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,4 +16,4 @@ export const handleHome = async (): Promise<Response> => {
|
||||
'content-type': 'text/html; charset=utf-8',
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import {
|
||||
createBucket,
|
||||
deleteBucket,
|
||||
findBucketByName,
|
||||
listBuckets,
|
||||
} from '../../../db/buckets';
|
||||
import { config } from '../../../config/index';
|
||||
import { createBucket, deleteBucket, findBucketByName, listBuckets } from '../../../db/buckets';
|
||||
import {
|
||||
countBucketObjects,
|
||||
findFileByBucketAndKey,
|
||||
@@ -22,18 +18,12 @@ import {
|
||||
listMultipartUploadsByBucket,
|
||||
} from '../../../db/multipart';
|
||||
import type { File } from '../../../db/schema';
|
||||
import { config } from '../../../config/index';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { cleanupTempFile, ensureExtension, getErrorMessage } from '../../../shared/utils/file';
|
||||
import {
|
||||
createChunkedObjectResponse,
|
||||
storeFileInTelegramChunks,
|
||||
} from '../../../utils/chunked-storage';
|
||||
import {
|
||||
cleanupTempFile,
|
||||
computeHash,
|
||||
ensureExtension,
|
||||
getErrorMessage,
|
||||
} from '../../../shared/utils/file';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { verifyPresignedUrl, verifySignature } from '../../../utils/s3/auth';
|
||||
import { S3_CORS_HEADERS, s3Headers } from '../../../utils/s3/headers';
|
||||
import { createGetObjectResponse, type ObjectPartSource } from '../../../utils/s3/object-stream';
|
||||
@@ -700,7 +690,14 @@ const streamBodyToTemp = async (
|
||||
const tempPath = `/tmp/filedrop-s3-${nanoid()}`;
|
||||
const writer = Bun.file(tempPath).writer();
|
||||
const hasher = new Bun.CryptoHasher('sha256');
|
||||
const reader = (body ?? new ReadableStream({ start(c) { c.close() } })).getReader();
|
||||
const reader = (
|
||||
body ??
|
||||
new ReadableStream({
|
||||
start(c) {
|
||||
c.close();
|
||||
},
|
||||
})
|
||||
).getReader();
|
||||
const SIGNATURE_BYTES = 16;
|
||||
const signatureChunks: Buffer[] = [];
|
||||
let signatureBytes = 0;
|
||||
@@ -1273,7 +1270,14 @@ const handleUploadPart = async (
|
||||
// Stream the part body to temp — O(1) memory, safe for large parts
|
||||
const tempPath = `/tmp/filedrop-mp-${nanoid()}`;
|
||||
const writer = Bun.file(tempPath).writer();
|
||||
const reader = (req.body ?? new ReadableStream({ start(c) { c.close() } })).getReader();
|
||||
const reader = (
|
||||
req.body ??
|
||||
new ReadableStream({
|
||||
start(c) {
|
||||
c.close();
|
||||
},
|
||||
})
|
||||
).getReader();
|
||||
const hasher = new Bun.CryptoHasher('sha256');
|
||||
let sizeBytes = 0;
|
||||
|
||||
@@ -1546,4 +1550,4 @@ const handleListParts = async (
|
||||
);
|
||||
|
||||
return s3Response(xml, 200, reqId, { 'content-type': 'application/xml' });
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { createWriteStream } from 'node:fs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { config } from '../../../config/index';
|
||||
import { findFileByHash } from '../../../db/files';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { metricsCollector } from '../../../shared/metrics/index';
|
||||
import {
|
||||
buildUploadResponse,
|
||||
checkFileSize,
|
||||
@@ -11,11 +14,8 @@ import {
|
||||
getErrorMessage,
|
||||
getFileType,
|
||||
} from '../../../shared/utils/file';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { metricsCollector } from '../../../shared/metrics/index';
|
||||
import { enqueuePreparedUpload, type PreparedUpload } from '../../../utils/uploadBatcher';
|
||||
import { storeFileInTelegramChunks } from '../../../utils/chunked-storage';
|
||||
import { findFileByHash } from '../../../db/files';
|
||||
import { enqueuePreparedUpload, type PreparedUpload } from '../../../utils/uploadBatcher';
|
||||
|
||||
/**
|
||||
* Maximum allowed size (in bytes) for a base64 JSON upload.
|
||||
@@ -399,4 +399,4 @@ export const handleUpload = async (req: Request): Promise<Response> => {
|
||||
} finally {
|
||||
metricsCollector.recordUploadTime(performance.now() - startTime);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { config } from '../../../config/index';
|
||||
import { createBucket, deleteBucket, findBucketByName, listBuckets } from '../../../db/buckets';
|
||||
import {
|
||||
countBucketObjects,
|
||||
@@ -7,10 +8,12 @@ import {
|
||||
listObjectsByPrefix,
|
||||
softDeleteFile,
|
||||
} from '../../../db/files-ext';
|
||||
import { config } from '../../../config/index';
|
||||
import { createChunkedObjectResponse, storeFileInTelegramChunks } from '../../../utils/chunked-storage';
|
||||
import { cleanupTempFile, computeHash, ensureExtension, getErrorMessage } from '../../../shared/utils/file';
|
||||
import logger from '../../../shared/logger/index';
|
||||
import { cleanupTempFile, ensureExtension, getErrorMessage } from '../../../shared/utils/file';
|
||||
import {
|
||||
createChunkedObjectResponse,
|
||||
storeFileInTelegramChunks,
|
||||
} from '../../../utils/chunked-storage';
|
||||
import { forwardToStorage, getFileInfo } from '../../../utils/telegram';
|
||||
|
||||
/**
|
||||
@@ -463,4 +466,4 @@ export const handleWebApiV1 = async (req: Request): Promise<Response> => {
|
||||
logger.error('Web API error', { path: pathname, error: getErrorMessage(error) });
|
||||
return jsonError('Internal server error', 500);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -43,8 +43,7 @@ const getSecret = (secret?: string): string => secret ?? config.adminApiToken;
|
||||
const getCookieName = (cookieName?: string): string => cookieName ?? config.sessionCookieName;
|
||||
const getMaxAgeMs = (maxAgeMs?: number): number => maxAgeMs ?? config.sessionMaxAgeMs;
|
||||
|
||||
const encodePayload = (value: string): string =>
|
||||
Buffer.from(value, 'utf8').toString('base64url');
|
||||
const encodePayload = (value: string): string => Buffer.from(value, 'utf8').toString('base64url');
|
||||
|
||||
const decodePayload = (value: string): string | null => {
|
||||
try {
|
||||
@@ -107,10 +106,7 @@ export const signCookiePayload = (payload: string, secret: string): string =>
|
||||
* @param secret - HMAC signing key.
|
||||
* @returns The unsigned payload string, or `null` on failure.
|
||||
*/
|
||||
export const verifyCookieSignature = (
|
||||
cookieValue: string,
|
||||
secret: string,
|
||||
): string | null => {
|
||||
export const verifyCookieSignature = (cookieValue: string, secret: string): string | null => {
|
||||
const separatorIndex = cookieValue.lastIndexOf(SIGNATURE_SEPARATOR);
|
||||
if (separatorIndex <= 0 || separatorIndex === cookieValue.length - 1) {
|
||||
return null;
|
||||
@@ -136,13 +132,7 @@ export const verifyCookieSignature = (
|
||||
* @returns The cookie attribute string (excluding name=value).
|
||||
*/
|
||||
const cookieAttributes = (maxAgeSeconds: number): string =>
|
||||
[
|
||||
`Max-Age=${maxAgeSeconds}`,
|
||||
'Path=/',
|
||||
'HttpOnly',
|
||||
'SameSite=Lax',
|
||||
'Secure',
|
||||
].join('; ');
|
||||
[`Max-Age=${maxAgeSeconds}`, 'Path=/', 'HttpOnly', 'SameSite=Lax', 'Secure'].join('; ');
|
||||
|
||||
/**
|
||||
* Creates a signed session cookie string suitable for use as a
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export { withRateLimit, cleanupRateLimitCache, checkRateLimit, clearRateLimitCache, getRateLimitStats } from '../../../utils/rateLimit';
|
||||
export {
|
||||
checkRateLimit,
|
||||
cleanupRateLimitCache,
|
||||
clearRateLimitCache,
|
||||
getRateLimitStats,
|
||||
withRateLimit,
|
||||
} from '../../../utils/rateLimit';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { config } from '../../../config/index';
|
||||
import { handleSwaggerHtml, handleSwaggerJson } from '../../../routes/swagger';
|
||||
import { extractS3BucketFromHost } from '../../../utils/s3/virtual-host';
|
||||
import { isS3Request } from '../../s3/auth';
|
||||
import { handleLogin, handleLogout, handleMe } from '../controllers/auth-controller';
|
||||
import { handleFileRedirect, handleFileInfo } from '../controllers/file-controller';
|
||||
import { handleFileInfo, handleFileRedirect } from '../controllers/file-controller';
|
||||
import { handleHealth } from '../controllers/health-controller';
|
||||
import { handleHome } from '../controllers/home-controller';
|
||||
import { handleS3Request } from '../controllers/s3-controller';
|
||||
import { handleSwaggerHtml, handleSwaggerJson } from '../../../routes/swagger';
|
||||
import { handleUpload } from '../controllers/upload-controller';
|
||||
import { handleWebApiV1 } from '../controllers/web-api-controller';
|
||||
import { requireAuth } from '../middleware/auth';
|
||||
import { withRateLimit } from '../middleware/rate-limit';
|
||||
import { isS3Request } from '../../s3/auth';
|
||||
import { extractS3BucketFromHost } from '../../../utils/s3/virtual-host';
|
||||
|
||||
/**
|
||||
* Extracts the S3 bucket name from the request host
|
||||
@@ -47,7 +47,7 @@ const shouldHandleS3 = (req: Request, headers: Record<string, string>): boolean
|
||||
* @param req - The incoming HTTP request.
|
||||
* @returns A Response from the S3 handler or a 405 response.
|
||||
*/
|
||||
const handleMaybeS3Root = (req: Request): Response | Promise<Response> => {
|
||||
const _handleMaybeS3Root = (req: Request): Response | Promise<Response> => {
|
||||
if (req.method === 'OPTIONS') {
|
||||
return handleS3Request(req, getS3RouteBucket(req));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user