@lacrous/omnicloud 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -242,6 +242,8 @@ interface HealthDTO {
242
242
  }
243
243
  interface IntegrityIssueDTO$1 {
244
244
  fileId: string;
245
+ /** Set when the issue is with a historical version rather than the current object. */
246
+ versionId?: string;
245
247
  name: string;
246
248
  kind: "missing" | "size_mismatch" | "unreadable" | "hash_mismatch";
247
249
  detail: string | null;
@@ -341,8 +343,14 @@ interface UploadOptions {
341
343
  retry?: number;
342
344
  }
343
345
  interface UploadInput {
344
- /** File content: Blob/File in the browser, Buffer/Uint8Array in Node. */
345
- data: Blob | Uint8Array;
346
+ /**
347
+ * File content: a Blob/File, a Uint8Array/Buffer, a web ReadableStream, or (in
348
+ * Node) a Readable stream. Streams are read in chunks; the caller never has to
349
+ * build one large buffer.
350
+ */
351
+ data?: Blob | Uint8Array | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>;
352
+ /** Node only: a path to read the file from. Use instead of `data`. */
353
+ path?: string;
346
354
  /** Filename; also used to derive the MIME type server-side. */
347
355
  name: string;
348
356
  }
@@ -351,6 +359,13 @@ interface DownloadProgress {
351
359
  total: number | null;
352
360
  percent: number | null;
353
361
  }
362
+ interface StreamedDownload {
363
+ stream: ReadableStream<Uint8Array>;
364
+ contentType: string;
365
+ /** Declared byte length, or null when the server did not send one. */
366
+ size: number | null;
367
+ sha256: string | null;
368
+ }
354
369
  interface DownloadResult {
355
370
  data: Buffer | Uint8Array;
356
371
  contentType: string;
@@ -393,6 +408,12 @@ declare class OmniCloudClient {
393
408
  /** @internal */
394
409
  withRetry<T>(operation: () => Promise<T>): Promise<T>;
395
410
  /** @internal */
411
+ /**
412
+ * Opens a binary response as a stream. Bytes are delivered as they arrive, so
413
+ * memory does not grow with the file. The stream errors with DOWNLOAD_INCOMPLETE
414
+ * if the body ends before Content-Length.
415
+ */
416
+ requestStream(path: string, onProgress?: (p: DownloadProgress) => void): Promise<StreamedDownload>;
396
417
  requestBinary(path: string, onProgress?: (p: DownloadProgress) => void): Promise<DownloadResult>;
397
418
  }
398
419
  declare class FilesApi {
@@ -413,6 +434,22 @@ declare class FilesApi {
413
434
  /** Uploads a new version of an existing file. */
414
435
  replace(id: string, input: UploadInput): Promise<FileDTO$1>;
415
436
  download(id: string, onProgress?: (p: DownloadProgress) => void): Promise<DownloadResult>;
437
+ /**
438
+ * Streams a file's bytes without holding the whole file in memory. Use this for
439
+ * large files. Read `stream` to the end: a truncated transfer errors instead of
440
+ * ending quietly.
441
+ */
442
+ downloadStream(id: string, onProgress?: (p: DownloadProgress) => void): Promise<StreamedDownload>;
443
+ /**
444
+ * Node only. Streams a file to `targetPath` through a `.part` file that is
445
+ * renamed into place only after the full length is verified. A truncated or
446
+ * failed transfer leaves nothing at `targetPath`.
447
+ */
448
+ downloadToFile(id: string, targetPath: string, onProgress?: (p: DownloadProgress) => void): Promise<{
449
+ path: string;
450
+ bytes: number;
451
+ sha256: string | null;
452
+ }>;
416
453
  /** URL suitable for direct download (anchor href). */
417
454
  downloadUrl(id: string): string;
418
455
  rename(id: string, name: string): Promise<FileDTO$1>;
@@ -567,6 +604,8 @@ declare const RESOURCE_TYPES: readonly ["file", "folder", "storage"];
567
604
  type ResourceType = (typeof RESOURCE_TYPES)[number];
568
605
  interface IntegrityIssueDTO {
569
606
  fileId: string;
607
+ /** Set when the issue is with a historical version rather than the current object. */
608
+ versionId?: string;
570
609
  name: string;
571
610
  kind: "missing" | "size_mismatch" | "unreadable" | "hash_mismatch";
572
611
  detail: string | null;
@@ -613,7 +652,14 @@ declare class DomainError extends Error {
613
652
  readonly code: ErrorCode;
614
653
  readonly status: number;
615
654
  readonly details?: unknown;
616
- constructor(code: ErrorCode, status: number, message: string, details?: unknown);
655
+ /** Whether repeating the same operation may succeed. Defaults to false. */
656
+ readonly retryable: boolean;
657
+ /** Server-requested delay before a retry, in seconds, when the provider gave one. */
658
+ readonly retryAfterSeconds?: number;
659
+ constructor(code: ErrorCode, status: number, message: string, details?: unknown, retry?: {
660
+ retryable?: boolean;
661
+ retryAfterSeconds?: number;
662
+ });
617
663
  }
618
664
  /**
619
665
  * Wraps an arbitrary provider failure as an UploadFailedError (the default
@@ -756,6 +802,19 @@ interface StorageStats {
756
802
  quotaBytes: number | null;
757
803
  }
758
804
 
805
+ /**
806
+ * Upload operations are the durable record of one logical upload. They exist so
807
+ * that a retried request (same operation id) can resume or replay instead of
808
+ * writing a second Telegram object and a second file record.
809
+ *
810
+ * PENDING accepted, Telegram write not started
811
+ * UPLOADING Telegram write in progress or its outcome unknown
812
+ * COMPLETED Telegram object stored and file record committed; result is final
813
+ * FAILED Telegram write definitively failed; the operation may be retried
814
+ * under a new id
815
+ */
816
+ type UploadOperationStatus = "PENDING" | "UPLOADING" | "COMPLETED" | "FAILED";
817
+
759
818
  /**
760
819
  * Repository interfaces. The application depends on these, not on a specific
761
820
  * database — the Prisma implementation lives in @omnicloud/database, and
@@ -777,6 +836,33 @@ interface SessionRepository {
777
836
  save(userId: string, stringSession: string): Promise<void>;
778
837
  delete(userId: string): Promise<void>;
779
838
  }
839
+ interface BrowserSessionRecord {
840
+ id: string;
841
+ userId: string;
842
+ tokenHash: string;
843
+ createdAt: Date;
844
+ expiresAt: Date;
845
+ revokedAt: Date | null;
846
+ lastUsedAt: Date | null;
847
+ userAgent: string | null;
848
+ ip: string | null;
849
+ }
850
+ /** Server-side browser sessions. Holds only token hashes, never raw tokens. */
851
+ interface BrowserSessionRepository {
852
+ create(input: {
853
+ userId: string;
854
+ tokenHash: string;
855
+ expiresAt: Date;
856
+ userAgent: string | null;
857
+ ip: string | null;
858
+ }): Promise<BrowserSessionRecord>;
859
+ findByTokenHash(tokenHash: string): Promise<BrowserSessionRecord | null>;
860
+ touch(id: string, at: Date): Promise<void>;
861
+ revoke(id: string, at: Date): Promise<void>;
862
+ revokeAllForUser(userId: string, at: Date): Promise<number>;
863
+ listActiveForUser(userId: string, now: Date): Promise<BrowserSessionRecord[]>;
864
+ deleteExpiredBefore(cutoff: Date): Promise<number>;
865
+ }
780
866
  interface StorageRepository {
781
867
  findByUserAndProvider(userId: string, provider: string): Promise<StorageRecord | null>;
782
868
  create(input: {
@@ -794,6 +880,12 @@ interface FolderCreateInput {
794
880
  }
795
881
  interface FolderRepository {
796
882
  create(input: FolderCreateInput): Promise<FolderRecord>;
883
+ /**
884
+ * Re-parents a folder only if the result stays acyclic. The ancestor check and
885
+ * the write are one atomic step, so two concurrent moves cannot each pass the
886
+ * check and together create a cycle. Throws ConflictError on a cycle.
887
+ */
888
+ moveSafely(id: string, newParentId: string | null): Promise<FolderRecord>;
797
889
  findById(id: string): Promise<FolderRecord | null>;
798
890
  /** Every folder belonging to the user (used for trees and cascade logic). */
799
891
  listByUser(userId: string): Promise<FolderRecord[]>;
@@ -827,6 +919,37 @@ interface FileCreateInput {
827
919
  sha256: string;
828
920
  telegramMessageId: number;
829
921
  }
922
+ interface UploadOperationRecord {
923
+ id: string;
924
+ userId: string;
925
+ operationId: string;
926
+ status: UploadOperationStatus;
927
+ /** Set once the Telegram object exists, so recovery can commit without re-uploading. */
928
+ telegramMessageId: number | null;
929
+ sha256: string | null;
930
+ size: number | null;
931
+ fileId: string | null;
932
+ error: string | null;
933
+ createdAt: Date;
934
+ updatedAt: Date;
935
+ }
936
+ /** Durable upload attempts, scoped to the owning user. */
937
+ interface UploadOperationRepository {
938
+ findByOperationId(userId: string, operationId: string): Promise<UploadOperationRecord | null>;
939
+ /** Operations for a user in the given states (used by reconciliation). */
940
+ listByStatus(userId: string, status: UploadOperationStatus): Promise<UploadOperationRecord[]>;
941
+ create(input: {
942
+ userId: string;
943
+ operationId: string;
944
+ }): Promise<UploadOperationRecord>;
945
+ /**
946
+ * Atomically moves an operation from `from` to `to` if, and only if, it is
947
+ * still in `from`. Returns false when another request already moved it, so
948
+ * exactly one request performs the upload.
949
+ */
950
+ claim(id: string, from: UploadOperationStatus, to: UploadOperationStatus): Promise<boolean>;
951
+ update(id: string, patch: Partial<Pick<UploadOperationRecord, "status" | "telegramMessageId" | "sha256" | "size" | "fileId" | "error">>): Promise<UploadOperationRecord>;
952
+ }
830
953
  interface FileRepository {
831
954
  create(input: FileCreateInput): Promise<FileRecord>;
832
955
  findById(id: string): Promise<FileRecord | null>;
@@ -873,6 +996,8 @@ interface FileRepository {
873
996
  telegramMessageId: number;
874
997
  }): Promise<FileVersionRecord>;
875
998
  listVersions(fileId: string): Promise<FileVersionRecord[]>;
999
+ /** All versions for many files in one query, grouped by file id. */
1000
+ listVersionsForFiles(fileIds: string[]): Promise<Map<string, FileVersionRecord[]>>;
876
1001
  findVersionById(versionId: string): Promise<FileVersionRecord | null>;
877
1002
  countVersions(fileId: string): Promise<number>;
878
1003
  deleteVersionsByFileIds(fileIds: string[]): Promise<void>;
@@ -901,6 +1026,8 @@ interface ActivityRepository {
901
1026
  interface Repos {
902
1027
  users: UserRepository;
903
1028
  sessions: SessionRepository;
1029
+ browserSessions: BrowserSessionRepository;
1030
+ uploadOperations: UploadOperationRepository;
904
1031
  storages: StorageRepository;
905
1032
  folders: FolderRepository;
906
1033
  files: FileRepository;
@@ -937,16 +1064,21 @@ interface TransferControl {
937
1064
  signal?: AbortSignal;
938
1065
  onProgress?: (progress: TransferProgress) => void;
939
1066
  }
940
- /** Upload input. `data` is a Buffer; `stream` is used for large files. */
1067
+ /**
1068
+ * Upload input. Exactly one of `data` (small, in memory) or `path` (a spooled
1069
+ * file on disk, read in slices by the provider) must be given.
1070
+ */
941
1071
  interface StorageUploadInput {
942
1072
  name: string;
943
1073
  mimeType: string;
944
1074
  /** Whole-object buffer (small files). */
945
1075
  data?: Buffer;
946
- /** Streaming source (large files). Either `data` or `stream` is required. */
947
- stream?: Readable;
948
- /** Total byte length, required when streaming. */
1076
+ /** Path to a spooled file (large files). Its bytes are never fully loaded. */
1077
+ path?: string;
1078
+ /** Total byte length of the object. Required with `path`. */
949
1079
  size?: number;
1080
+ /** SHA-256 of the spooled bytes, computed while they were written. Required with `path`. */
1081
+ sha256?: string;
950
1082
  }
951
1083
  interface StorageHealth {
952
1084
  /** Reachable and usable. */
@@ -972,6 +1104,12 @@ interface StorageProvider {
972
1104
  delete(ref: StoredRef): Promise<void>;
973
1105
  exists(ref: StoredRef): Promise<boolean>;
974
1106
  stat(ref: StoredRef): Promise<StoredObject | null>;
1107
+ /**
1108
+ * Lists the objects the backing store holds, newest first, read-only. Used by
1109
+ * reconciliation; it must never modify anything. Implementations page through
1110
+ * the store and stop once `limit` objects are returned.
1111
+ */
1112
+ listObjects(limit: number): Promise<StoredObject[]>;
975
1113
  /** Validates that the backing store is reachable and usable. */
976
1114
  healthCheck(): Promise<StorageHealth>;
977
1115
  }
@@ -1008,21 +1146,30 @@ declare class StorageEngine {
1008
1146
  */
1009
1147
  upload(input: StorageUploadInput, control?: TransferControl): Promise<EngineUploadResult>;
1010
1148
  download(ref: StoredRef, control?: TransferControl): Promise<Buffer>;
1011
- /** Streams the object, computing the checksum on the fly when requested. */
1012
- downloadStream(ref: StoredRef, control?: TransferControl): Promise<{
1013
- stream: Readable;
1014
- hash: () => string | null;
1015
- }>;
1149
+ /**
1150
+ * Streams the object and verifies its SHA-256 against `expectedSha256`.
1151
+ *
1152
+ * The last chunk is held back until the digest of everything before it has
1153
+ * been checked, so a corrupt object errors the stream before its final bytes
1154
+ * are released. A consumer therefore never sees a complete-looking body that
1155
+ * fails the checksum. Memory stays bounded to about two provider chunks.
1156
+ */
1157
+ downloadStream(ref: StoredRef, expectedSha256: string, control?: TransferControl): Promise<Readable>;
1016
1158
  remove(ref: StoredRef): Promise<void>;
1017
1159
  exists(ref: StoredRef): Promise<boolean>;
1160
+ /** Read-only listing of stored objects, for reconciliation. Never modifies anything. */
1161
+ list(limit: number): Promise<StoredObject[]>;
1018
1162
  stat(ref: StoredRef): Promise<StoredObject | null>;
1019
1163
  health(): Promise<StorageHealth>;
1020
1164
  verifyIntegrity(data: Buffer, expectedSha256: string): Promise<boolean>;
1021
- /** Materializes an upload input so the checksum can be computed. */
1022
- private readInput;
1023
1165
  private withRetry;
1024
1166
  }
1025
1167
 
1168
+ interface OperationSink {
1169
+ info(record: Record<string, unknown>, message: string): void;
1170
+ warn(record: Record<string, unknown>, message: string): void;
1171
+ }
1172
+
1026
1173
  interface RecordActivityInput {
1027
1174
  userId: string;
1028
1175
  action: ActivityAction;
@@ -1065,13 +1212,27 @@ interface FileDownload {
1065
1212
  data: Buffer;
1066
1213
  integrityVerified: boolean;
1067
1214
  }
1215
+ interface FileStreamDownload {
1216
+ record: FileRecord;
1217
+ /** Errors with IntegrityCheckError instead of ending if the bytes do not match. */
1218
+ stream: Readable;
1219
+ }
1068
1220
  type EngineResolver = (userId: string) => Promise<StorageEngine>;
1069
1221
  interface FileUploadInput {
1070
1222
  folderId: string | null;
1071
1223
  name: string;
1072
- data: Buffer;
1224
+ /** In-memory content. Use `spooled` for anything large. */
1225
+ data?: Buffer;
1226
+ /** A file already written to disk by `spoolToFile`, with its checksum. */
1227
+ spooled?: {
1228
+ path: string;
1229
+ size: number;
1230
+ sha256: string;
1231
+ };
1073
1232
  /** When set, uploads a new version of this file instead of creating one. */
1074
1233
  replaceFileId?: string;
1234
+ /** Client-supplied id that makes the upload idempotent across retries. */
1235
+ operationId?: string;
1075
1236
  /** Progress callback forwarded from the transport layer. */
1076
1237
  onProgress?: (progress: TransferProgress) => void;
1077
1238
  signal?: AbortSignal;
@@ -1090,8 +1251,28 @@ declare class FileService {
1090
1251
  private readonly folders;
1091
1252
  private readonly engineFor;
1092
1253
  private readonly activity;
1093
- constructor(files: FileRepository, folders: FolderRepository, engineFor: EngineResolver, activity?: ActivityRecorder);
1254
+ private readonly operations;
1255
+ private readonly log;
1256
+ constructor(files: FileRepository, folders: FolderRepository, engineFor: EngineResolver, activity?: ActivityRecorder, operations?: UploadOperationRepository | null, log?: OperationSink | null);
1094
1257
  upload(userId: string, input: FileUploadInput): Promise<FileRecord>;
1258
+ /**
1259
+ * Idempotent upload keyed by a client-supplied operation id. A retry never
1260
+ * writes a second Telegram object: a completed operation returns its file, and
1261
+ * an operation whose object was already stored is committed without uploading.
1262
+ */
1263
+ private uploadOnce;
1264
+ /**
1265
+ * Follows an operation another request is driving, for a bounded time. Returns
1266
+ * the finished file if the winner completes, or the stored object's commit if
1267
+ * it has stored one. Returns null when the winner is still in progress after the
1268
+ * budget, so the caller can report a conflict instead of waiting forever.
1269
+ */
1270
+ private followWinner;
1271
+ /** Commits metadata for an object that is already in Telegram. */
1272
+ private commitStoredObject;
1273
+ private performUpload;
1274
+ /** Persists the file (or the new version of a file) for an object already stored. */
1275
+ private commitRecord;
1095
1276
  /** Uploads a new version of an existing file and makes it current. */
1096
1277
  private replaceVersion;
1097
1278
  list(userId: string, folderId: string | null): Promise<FileRecord[]>;
@@ -1116,12 +1297,20 @@ declare class FileService {
1116
1297
  * retry, rather than silently orphaning the storage object.
1117
1298
  */
1118
1299
  deletePermanently(userId: string, id: string): Promise<void>;
1300
+ private performPermanentDelete;
1119
1301
  /**
1120
1302
  * v0.1-compatible hard delete used by the current API: permanently removes
1121
1303
  * the file. Retained so existing clients keep working.
1122
1304
  */
1123
1305
  delete(userId: string, id: string): Promise<void>;
1124
1306
  download(userId: string, id: string, control?: TransferControl): Promise<FileDownload>;
1307
+ /**
1308
+ * Streaming download for large files. The caller must consume `stream` to
1309
+ * the end and then await `verified` to learn whether the bytes match the
1310
+ * stored checksum. The download activity is recorded when the stream opens.
1311
+ */
1312
+ downloadStreamed(userId: string, id: string, control?: TransferControl): Promise<FileStreamDownload>;
1313
+ private performStreamedDownload;
1125
1314
  /** Records an "open" event (the UI opening the details panel, say). */
1126
1315
  touch(userId: string, id: string, action?: "open"): Promise<void>;
1127
1316
  /**
@@ -1130,7 +1319,9 @@ declare class FileService {
1130
1319
  */
1131
1320
  batch(userId: string, ids: string[], operation: "trash" | "restore" | "delete" | "star" | "unstar" | "move", options?: {
1132
1321
  folderId?: string | null;
1322
+ operationId?: string;
1133
1323
  }): Promise<{
1324
+ operationId?: string;
1134
1325
  requested: number;
1135
1326
  succeeded: number;
1136
1327
  failed: number;
@@ -1287,6 +1478,7 @@ declare class IntegrityService {
1287
1478
  constructor(files: FileRepository, engineFor: EngineResolver);
1288
1479
  check(userId: string, options?: IntegrityCheckOptions): Promise<IntegrityReportDTO>;
1289
1480
  private inspect;
1481
+ private inspectObject;
1290
1482
  }
1291
1483
 
1292
1484
  /**
@@ -1385,9 +1577,20 @@ declare class TelegramStorageProvider implements StorageProvider {
1385
1577
  constructor(client: TelegramClient, options: TelegramStorageOptions);
1386
1578
  put(input: StorageUploadInput, control?: TransferControl): Promise<StoredObject>;
1387
1579
  get(ref: StoredRef, control?: TransferControl): Promise<Buffer>;
1580
+ /**
1581
+ * Streams the object in Telegram-sized chunks, so memory use stays bounded
1582
+ * by one chunk regardless of file size. The first request happens here so
1583
+ * that a missing message fails before the caller starts consuming bytes.
1584
+ */
1388
1585
  getStream(ref: StoredRef, control?: TransferControl): Promise<Readable>;
1389
1586
  delete(ref: StoredRef): Promise<void>;
1390
1587
  exists(ref: StoredRef): Promise<boolean>;
1588
+ /**
1589
+ * Read-only listing of stored documents in the channel, newest first, up to
1590
+ * `limit`. Only messages that carry a document are returned; text messages and
1591
+ * service messages are skipped. Nothing is modified.
1592
+ */
1593
+ listObjects(limit: number): Promise<StoredObject[]>;
1391
1594
  stat(ref: StoredRef): Promise<StoredObject | null>;
1392
1595
  /**
1393
1596
  * Validates that the client is connected and the storage channel is
@@ -1395,7 +1598,6 @@ declare class TelegramStorageProvider implements StorageProvider {
1395
1598
  */
1396
1599
  healthCheck(): Promise<StorageHealth>;
1397
1600
  private throwIfAborted;
1398
- private materialize;
1399
1601
  private documentSize;
1400
1602
  private requireMessage;
1401
1603
  private getMessage;
@@ -1439,4 +1641,4 @@ declare class TelegramConnectionService {
1439
1641
  private disconnectQuietly;
1440
1642
  }
1441
1643
 
1442
- export { type ActivityEventDTO, type ActivityEventRecord, type ActivityPageDTO, type ActivityRecorder, ActivityService, type ApiErrorBody, type BatchResultDTO, type ConnectionState, type ConnectionStatus, DomainError, type DownloadProgress, type DownloadResult, ERROR_CODES$1 as ERROR_CODES, type EmptyTrashResultDTO, type EngineResolver, type EngineRetryPolicy, type EngineUploadResult, type ErrorCode$1 as ErrorCode, type FileCategory, type FileDTO$1 as FileDTO, type FileDownload, type FileRecord, FileService, type FileTypeBucket, type FileVersionDTO, type FileVersionRecord, type FilesPageDTO, type FolderDTO$1 as FolderDTO, type FolderMutationResult, type FolderMutationResultDTO, type FolderRecord, FolderService, type FoldersPageDTO, type HealthDTO, type HealthStatus, type IntegrityCheckOptions, type IntegrityIssueDTO$1 as IntegrityIssueDTO, type IntegrityReportDTO$1 as IntegrityReportDTO, IntegrityService, type ItemQuery, type ItemStatus, type ListQuery, OmniCloudClient, type OmniCloudClientOptions, OmniCloudError, type PageRequest, type Paged, type PaginationDTO$1 as PaginationDTO, type RecentItemDTO$1 as RecentItemDTO, type RecentPageDTO$1 as RecentPageDTO, RecentService, type Repos, type RetryOptions, type SearchResultDTO$1 as SearchResultDTO, SearchService, type SessionInfo, type SortField, type SortOrder, StatsService, type StorageDTO, StorageEngine, type StorageHealth, type StorageHealthDTO, type StorageProvider, type StorageRecord, type StorageStats, type StorageStatsDTO, type StorageTypeBreakdownDTO, type StorageUploadInput, type StoredObject, type StoredRef, TELEGRAM_PROVIDER, TelegramClientManager, TelegramConnectionService, type TelegramCredentials, type TelegramStorageOptions, TelegramStorageProvider, type TelegramVerifyResponse, type TransferControl, type TransferProgress, type TrashPageDTO, TrashService, type UploadInput, type UploadOptions, type UploadProgress, type UserDTO, type UserRecord, fileCategory, isFileCategory, mapProviderError, mapTelegramError, mimeFromFilename, mimeMatchersForType, noopActivityRecorder, paginationMeta, parseSearchQuery, parseSize, sanitizeFileName, sha256Hex };
1644
+ export { type ActivityEventDTO, type ActivityEventRecord, type ActivityPageDTO, type ActivityRecorder, ActivityService, type ApiErrorBody, type BatchResultDTO, type ConnectionState, type ConnectionStatus, DomainError, type DownloadProgress, type DownloadResult, ERROR_CODES$1 as ERROR_CODES, type EmptyTrashResultDTO, type EngineResolver, type EngineRetryPolicy, type EngineUploadResult, type ErrorCode$1 as ErrorCode, type FileCategory, type FileDTO$1 as FileDTO, type FileDownload, type FileRecord, FileService, type FileTypeBucket, type FileVersionDTO, type FileVersionRecord, type FilesPageDTO, type FolderDTO$1 as FolderDTO, type FolderMutationResult, type FolderMutationResultDTO, type FolderRecord, FolderService, type FoldersPageDTO, type HealthDTO, type HealthStatus, type IntegrityCheckOptions, type IntegrityIssueDTO$1 as IntegrityIssueDTO, type IntegrityReportDTO$1 as IntegrityReportDTO, IntegrityService, type ItemQuery, type ItemStatus, type ListQuery, OmniCloudClient, type OmniCloudClientOptions, OmniCloudError, type PageRequest, type Paged, type PaginationDTO$1 as PaginationDTO, type RecentItemDTO$1 as RecentItemDTO, type RecentPageDTO$1 as RecentPageDTO, RecentService, type Repos, type RetryOptions, type SearchResultDTO$1 as SearchResultDTO, SearchService, type SessionInfo, type SortField, type SortOrder, StatsService, type StorageDTO, StorageEngine, type StorageHealth, type StorageHealthDTO, type StorageProvider, type StorageRecord, type StorageStats, type StorageStatsDTO, type StorageTypeBreakdownDTO, type StorageUploadInput, type StoredObject, type StoredRef, type StreamedDownload, TELEGRAM_PROVIDER, TelegramClientManager, TelegramConnectionService, type TelegramCredentials, type TelegramStorageOptions, TelegramStorageProvider, type TelegramVerifyResponse, type TransferControl, type TransferProgress, type TrashPageDTO, TrashService, type UploadInput, type UploadOptions, type UploadProgress, type UserDTO, type UserRecord, fileCategory, isFileCategory, mapProviderError, mapTelegramError, mimeFromFilename, mimeMatchersForType, noopActivityRecorder, paginationMeta, parseSearchQuery, parseSize, sanitizeFileName, sha256Hex };