- Extract shared utils: asSafeChunkSize (validation.ts), S3 detection (s3-detection.ts) - Remove dead _handleMaybeS3Root from index.ts and routes/index.ts - Remove dead _asArray from file-controller.ts - Consolidate maybeCompressChunk into shared compress.ts - Extract checkConditionalHeaders helper, remove ~120 lines dupe in s3-controller - Remove 500+ lines dead code from s3-object.ts (unused use cases + helpers) - Delegate upload-file.ts chunked path to ChunkedStorage, remove dupe - Fix broken dynamic import in file-controller.ts → proper DI - Fix test/files.test.ts import path and mocks [skip ci]
166 lines
5.4 KiB
TypeScript
166 lines
5.4 KiB
TypeScript
import type { File } from '../../domain/entities/file';
|
|
import type { IBucketRepository } from '../../domain/ports/bucket-repository';
|
|
import type { IFilePartRepository } from '../../domain/ports/file-part-repository';
|
|
import type { IFileRepository } from '../../domain/ports/file-repository';
|
|
import type { IMultipartRepository } from '../../domain/ports/multipart-repository';
|
|
import type { ITelegramService, TelegramFileInfo } from '../../domain/ports/telegram-service';
|
|
import type { CompressionAlgorithm } from '../../shared/utils/compress';
|
|
|
|
// ─── Types ──────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* A single part source for building a multi-part streaming response.
|
|
* Each part corresponds to a Telegram-stored file chunk.
|
|
*/
|
|
export interface ObjectPartSource {
|
|
/** Telegram file identifier for retrieving this part. */
|
|
telegramFileId: string;
|
|
/** Telegram CDN URL for downloading this part. */
|
|
telegramUrl: string;
|
|
/** Original size of this part in bytes. */
|
|
sizeBytes: number;
|
|
/** 1-based part number within the object. */
|
|
partNumber: number;
|
|
/** Stored (post-compression) size in bytes, when applicable. */
|
|
storedSizeBytes?: number;
|
|
/** Compression algorithm applied, or null if uncompressed. */
|
|
compressionAlgorithm?: CompressionAlgorithm;
|
|
}
|
|
|
|
/**
|
|
* A regular (direct) S3 object resolved to a Telegram CDN URL.
|
|
*/
|
|
export interface DirectObjectResult {
|
|
/** Discriminant. */
|
|
type: 'direct';
|
|
/** The resolved file entity. */
|
|
file: File;
|
|
/** Full Telegram CDN URL for downloading the object. */
|
|
telegramUrl: string;
|
|
/** Telegram file metadata. */
|
|
fileInfo: TelegramFileInfo;
|
|
}
|
|
|
|
/**
|
|
* A chunked S3 object stored across multiple Telegram file parts.
|
|
*/
|
|
export interface ChunkedObjectResult {
|
|
/** Discriminant. */
|
|
type: 'chunked';
|
|
/** The resolved file entity. */
|
|
file: File;
|
|
}
|
|
|
|
/**
|
|
* An S3 object assembled from a completed multipart upload.
|
|
*/
|
|
export interface MultipartObjectResult {
|
|
/** Discriminant. */
|
|
type: 'multipart';
|
|
/** The resolved file entity. */
|
|
file: File;
|
|
/** Resolved part sources with Telegram CDN URLs. */
|
|
parts: ObjectPartSource[];
|
|
}
|
|
|
|
/**
|
|
* Discriminated union of all possible S3 get-object outcomes.
|
|
*/
|
|
export type GetObjectResult = DirectObjectResult | ChunkedObjectResult | MultipartObjectResult;
|
|
|
|
/**
|
|
* Result of an S3 put-object operation.
|
|
*/
|
|
export interface PutObjectResult {
|
|
/** SHA-256 hex digest of the object content. */
|
|
etag: string;
|
|
}
|
|
|
|
/**
|
|
* Result of an S3 copy-object operation.
|
|
*/
|
|
export interface CopyObjectResult {
|
|
/** SHA-256 hex digest of the source object content. */
|
|
etag: string;
|
|
/** ISO-8601 timestamp of the copy operation. */
|
|
lastModified: string;
|
|
}
|
|
|
|
/**
|
|
* A single S3 object as returned in listing results.
|
|
*/
|
|
export interface ListObjectEntry {
|
|
/** The object key (full path within the bucket). */
|
|
key: string;
|
|
/** Object size in bytes. */
|
|
sizeBytes: number;
|
|
/** SHA-256 hex digest or fallback identifier. */
|
|
etag: string;
|
|
/** ISO-8601 timestamp of last modification. */
|
|
lastModified: string;
|
|
/** MIME type of the stored object. */
|
|
mimeType: string;
|
|
}
|
|
|
|
/**
|
|
* Result of an S3 list-objects operation (both V1 and V2).
|
|
*/
|
|
export interface ListObjectsResult {
|
|
/** Array of object summaries. */
|
|
objects: ListObjectEntry[];
|
|
/** Common prefixes when a delimiter was used. */
|
|
prefixes: string[];
|
|
/** Whether more results are available. */
|
|
isTruncated: boolean;
|
|
/** The last key in the returned page, for use as the next marker. */
|
|
nextMarker: string | null;
|
|
}
|
|
|
|
/**
|
|
* Head-object metadata.
|
|
*/
|
|
export interface HeadObjectMetadata {
|
|
/** MIME type of the object. */
|
|
contentType: string;
|
|
/** Object size in bytes. */
|
|
contentLength: number;
|
|
/** Entity tag (SHA-256 hex digest or fallback). */
|
|
etag: string;
|
|
/** ISO-8601 timestamp of last modification. */
|
|
lastModified: string;
|
|
}
|
|
|
|
// ─── Config ─────────────────────────────────────────────────────────
|
|
|
|
/** Subset of application configuration consumed by the s3-object use cases. */
|
|
export interface S3ObjectConfig {
|
|
/** Maximum chunk size in bytes for Telegram chunked uploads. */
|
|
telegramChunkSizeBytes: number;
|
|
/** Whether gzip compression is enabled for chunked uploads. */
|
|
compressChunkedUploads: boolean;
|
|
/** Minimum chunk size in bytes below which compression is skipped. */
|
|
chunkCompressionMinSizeBytes: number;
|
|
/** Telegram chat ID where file parts are stored. */
|
|
storageChatId: number;
|
|
/** Server base URL for constructing download links. */
|
|
baseUrl: string;
|
|
/** Whether to proxy S3 GET requests through the server. */
|
|
proxyS3Get: boolean;
|
|
}
|
|
|
|
/** Dependencies required by the s3-object use case factories. */
|
|
export interface S3ObjectDeps {
|
|
/** Bucket repository for bucket lookups. */
|
|
bucketRepo: IBucketRepository;
|
|
/** File repository for object CRUD operations. */
|
|
fileRepo: IFileRepository;
|
|
/** File-part repository for chunked upload part records. */
|
|
filePartRepo: IFilePartRepository;
|
|
/** Multipart repository for resolving multipart-upload objects. */
|
|
multipartRepo: IMultipartRepository;
|
|
/** Telegram service for uploading and resolving file metadata. */
|
|
telegramService: ITelegramService;
|
|
/** Application configuration subset. */
|
|
config: S3ObjectConfig;
|
|
}
|