@lacrous/omnicloud 0.2.0 → 0.2.1
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 +1051 -57
- package/dist/index.d.ts +1051 -57
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,80 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { TelegramClient } from 'telegram';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Search query parsing, pagination and sorting primitives.
|
|
6
|
+
*
|
|
7
|
+
* Self-contained (no runtime imports from the package root) so the API, web
|
|
8
|
+
* app and SDK can all share one query language without import cycles.
|
|
9
|
+
*
|
|
10
|
+
* Query language (v0.2):
|
|
11
|
+
* report → name contains "report"
|
|
12
|
+
* name:report → same, explicit
|
|
13
|
+
* type:pdf type:image type:application/zip
|
|
14
|
+
* ext:zip → file extension (no dot)
|
|
15
|
+
* size:>100MB size:<1KB size:5mb
|
|
16
|
+
* folder:Projects → folder-name filter
|
|
17
|
+
* starred:true trashed:true
|
|
18
|
+
* after:2026-01-01 before:2026-06-01
|
|
19
|
+
*/
|
|
20
|
+
declare const SORT_FIELDS: readonly ["name", "size", "createdAt", "updatedAt", "type"];
|
|
21
|
+
type SortField = (typeof SORT_FIELDS)[number];
|
|
22
|
+
declare const SORT_ORDERS: readonly ["asc", "desc"];
|
|
23
|
+
type SortOrder = (typeof SORT_ORDERS)[number];
|
|
24
|
+
declare const ITEM_STATUSES: readonly ["active", "trashed", "all"];
|
|
25
|
+
type ItemStatus = (typeof ITEM_STATUSES)[number];
|
|
26
|
+
/** Query parameters accepted by the file/folder listing endpoints. */
|
|
27
|
+
interface ListQuery {
|
|
28
|
+
folderId?: string | null;
|
|
29
|
+
page?: number;
|
|
30
|
+
limit?: number;
|
|
31
|
+
sort?: SortField;
|
|
32
|
+
order?: SortOrder;
|
|
33
|
+
/** MIME type or coarse category (image, video, pdf, document, …). */
|
|
34
|
+
type?: string;
|
|
35
|
+
/** File extension without the dot. */
|
|
36
|
+
ext?: string;
|
|
37
|
+
starred?: boolean;
|
|
38
|
+
status?: ItemStatus;
|
|
39
|
+
/** Name substring filter. */
|
|
40
|
+
q?: string;
|
|
41
|
+
/** Folder-name filter (search parser); resolved to ids by the caller. */
|
|
42
|
+
folderName?: string;
|
|
43
|
+
minSize?: number;
|
|
44
|
+
maxSize?: number;
|
|
45
|
+
/** Inclusive date bounds (ISO strings). */
|
|
46
|
+
from?: string;
|
|
47
|
+
to?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Parses "100MB", "1.5gb", "512" into bytes. Returns null when unparseable. */
|
|
50
|
+
declare function parseSize(value: string): number | null;
|
|
51
|
+
/** Parses a raw user query string into structured filters. */
|
|
52
|
+
declare function parseSearchQuery(input: string, base?: ListQuery): {
|
|
53
|
+
query: ListQuery;
|
|
54
|
+
freeText: string;
|
|
55
|
+
};
|
|
56
|
+
/** Builds the pagination envelope for a result page. */
|
|
57
|
+
declare function paginationMeta(page: number, limit: number, total: number): {
|
|
58
|
+
page: number;
|
|
59
|
+
limit: number;
|
|
60
|
+
total: number;
|
|
61
|
+
hasMore: boolean;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** Derives a MIME type from the filename extension. Never trusts client input. */
|
|
65
|
+
declare function mimeFromFilename(filename: string): string;
|
|
66
|
+
type FileCategory = "image" | "video" | "audio" | "pdf" | "archive" | "document" | "text" | "other";
|
|
67
|
+
/** Coarse category used for icon selection in the UI. */
|
|
68
|
+
declare function fileCategory(mimeType: string): FileCategory;
|
|
69
|
+
declare function isFileCategory(value: string): value is FileCategory;
|
|
70
|
+
/**
|
|
71
|
+
* Expands a `type:` filter into a set of MIME matchers.
|
|
72
|
+
*
|
|
73
|
+
* Accepts either a coarse category ("image", "pdf") or an exact MIME type
|
|
74
|
+
* ("application/pdf"); the repository layer turns these into prefix/equality
|
|
75
|
+
* filters. Returns null when the value matches nothing usable.
|
|
76
|
+
*/
|
|
77
|
+
declare function mimeMatchersForType(value: string): readonly string[] | null;
|
|
6
78
|
|
|
7
79
|
/**
|
|
8
80
|
* Data transfer objects, constants and error codes shared between the API,
|
|
@@ -48,7 +120,7 @@ type TelegramVerifyResponse = {
|
|
|
48
120
|
} | {
|
|
49
121
|
status: "password_required";
|
|
50
122
|
};
|
|
51
|
-
interface FileDTO {
|
|
123
|
+
interface FileDTO$1 {
|
|
52
124
|
id: string;
|
|
53
125
|
name: string;
|
|
54
126
|
size: number;
|
|
@@ -63,7 +135,7 @@ interface FileDTO {
|
|
|
63
135
|
createdAt: string;
|
|
64
136
|
updatedAt: string;
|
|
65
137
|
}
|
|
66
|
-
interface FolderDTO {
|
|
138
|
+
interface FolderDTO$1 {
|
|
67
139
|
id: string;
|
|
68
140
|
name: string;
|
|
69
141
|
parentId: string | null;
|
|
@@ -84,10 +156,10 @@ interface FileVersionDTO {
|
|
|
84
156
|
isCurrent: boolean;
|
|
85
157
|
createdAt: string;
|
|
86
158
|
}
|
|
87
|
-
interface SearchResultDTO {
|
|
88
|
-
files: FileDTO[];
|
|
89
|
-
folders: FolderDTO[];
|
|
90
|
-
pagination: PaginationDTO;
|
|
159
|
+
interface SearchResultDTO$1 {
|
|
160
|
+
files: FileDTO$1[];
|
|
161
|
+
folders: FolderDTO$1[];
|
|
162
|
+
pagination: PaginationDTO$1;
|
|
91
163
|
}
|
|
92
164
|
/** Result of a recursive folder deletion / trash operation. */
|
|
93
165
|
interface FolderMutationResultDTO {
|
|
@@ -100,42 +172,42 @@ interface EmptyTrashResultDTO {
|
|
|
100
172
|
failedFiles: number;
|
|
101
173
|
}
|
|
102
174
|
|
|
103
|
-
interface PaginationDTO {
|
|
175
|
+
interface PaginationDTO$1 {
|
|
104
176
|
page: number;
|
|
105
177
|
limit: number;
|
|
106
178
|
total: number;
|
|
107
179
|
hasMore: boolean;
|
|
108
180
|
}
|
|
109
181
|
interface FilesPageDTO {
|
|
110
|
-
files: FileDTO[];
|
|
111
|
-
pagination: PaginationDTO;
|
|
182
|
+
files: FileDTO$1[];
|
|
183
|
+
pagination: PaginationDTO$1;
|
|
112
184
|
}
|
|
113
185
|
interface FoldersPageDTO {
|
|
114
|
-
folders: FolderDTO[];
|
|
115
|
-
pagination: PaginationDTO;
|
|
186
|
+
folders: FolderDTO$1[];
|
|
187
|
+
pagination: PaginationDTO$1;
|
|
116
188
|
}
|
|
117
189
|
interface TrashPageDTO {
|
|
118
|
-
files: FileDTO[];
|
|
119
|
-
folders: FolderDTO[];
|
|
120
|
-
pagination: PaginationDTO;
|
|
190
|
+
files: FileDTO$1[];
|
|
191
|
+
folders: FolderDTO$1[];
|
|
192
|
+
pagination: PaginationDTO$1;
|
|
121
193
|
}
|
|
122
|
-
interface RecentItemDTO {
|
|
123
|
-
file: FileDTO;
|
|
124
|
-
lastAction: ActivityAction;
|
|
194
|
+
interface RecentItemDTO$1 {
|
|
195
|
+
file: FileDTO$1;
|
|
196
|
+
lastAction: ActivityAction$1;
|
|
125
197
|
lastActionAt: string;
|
|
126
198
|
}
|
|
127
|
-
interface RecentPageDTO {
|
|
128
|
-
items: RecentItemDTO[];
|
|
129
|
-
pagination: PaginationDTO;
|
|
199
|
+
interface RecentPageDTO$1 {
|
|
200
|
+
items: RecentItemDTO$1[];
|
|
201
|
+
pagination: PaginationDTO$1;
|
|
130
202
|
}
|
|
131
|
-
declare const ACTIVITY_ACTIONS: readonly ["upload", "download", "open", "rename", "move", "star", "unstar", "trash", "restore", "delete", "create_folder", "replace"];
|
|
132
|
-
type ActivityAction = (typeof ACTIVITY_ACTIONS)[number];
|
|
133
|
-
declare const RESOURCE_TYPES: readonly ["file", "folder", "storage"];
|
|
134
|
-
type ResourceType = (typeof RESOURCE_TYPES)[number];
|
|
203
|
+
declare const ACTIVITY_ACTIONS$1: readonly ["upload", "download", "open", "rename", "move", "star", "unstar", "trash", "restore", "delete", "create_folder", "replace"];
|
|
204
|
+
type ActivityAction$1 = (typeof ACTIVITY_ACTIONS$1)[number];
|
|
205
|
+
declare const RESOURCE_TYPES$1: readonly ["file", "folder", "storage"];
|
|
206
|
+
type ResourceType$1 = (typeof RESOURCE_TYPES$1)[number];
|
|
135
207
|
interface ActivityEventDTO {
|
|
136
208
|
id: string;
|
|
137
|
-
action: ActivityAction;
|
|
138
|
-
resourceType: ResourceType;
|
|
209
|
+
action: ActivityAction$1;
|
|
210
|
+
resourceType: ResourceType$1;
|
|
139
211
|
resourceId: string;
|
|
140
212
|
resourceName: string | null;
|
|
141
213
|
metadata: Record<string, unknown> | null;
|
|
@@ -143,7 +215,7 @@ interface ActivityEventDTO {
|
|
|
143
215
|
}
|
|
144
216
|
interface ActivityPageDTO {
|
|
145
217
|
events: ActivityEventDTO[];
|
|
146
|
-
pagination: PaginationDTO;
|
|
218
|
+
pagination: PaginationDTO$1;
|
|
147
219
|
}
|
|
148
220
|
interface StorageTypeBreakdownDTO {
|
|
149
221
|
category: string;
|
|
@@ -158,7 +230,7 @@ interface StorageStatsDTO {
|
|
|
158
230
|
trashFileCount: number;
|
|
159
231
|
starredCount: number;
|
|
160
232
|
byType: StorageTypeBreakdownDTO[];
|
|
161
|
-
largestFiles: FileDTO[];
|
|
233
|
+
largestFiles: FileDTO$1[];
|
|
162
234
|
quotaBytes: number | null;
|
|
163
235
|
}
|
|
164
236
|
interface HealthDTO {
|
|
@@ -168,20 +240,20 @@ interface HealthDTO {
|
|
|
168
240
|
uptimeSeconds: number;
|
|
169
241
|
version: string;
|
|
170
242
|
}
|
|
171
|
-
interface IntegrityIssueDTO {
|
|
243
|
+
interface IntegrityIssueDTO$1 {
|
|
172
244
|
fileId: string;
|
|
173
245
|
name: string;
|
|
174
246
|
kind: "missing" | "size_mismatch" | "unreadable" | "hash_mismatch";
|
|
175
247
|
detail: string | null;
|
|
176
248
|
}
|
|
177
|
-
interface IntegrityReportDTO {
|
|
249
|
+
interface IntegrityReportDTO$1 {
|
|
178
250
|
checkedAt: string;
|
|
179
251
|
filesChecked: number;
|
|
180
252
|
healthy: number;
|
|
181
253
|
missing: number;
|
|
182
254
|
inconsistent: number;
|
|
183
255
|
unreadable: number;
|
|
184
|
-
issues: IntegrityIssueDTO[];
|
|
256
|
+
issues: IntegrityIssueDTO$1[];
|
|
185
257
|
durationMs: number;
|
|
186
258
|
}
|
|
187
259
|
interface BatchResultDTO {
|
|
@@ -190,12 +262,12 @@ interface BatchResultDTO {
|
|
|
190
262
|
failed: number;
|
|
191
263
|
errors: {
|
|
192
264
|
id: string;
|
|
193
|
-
code: ErrorCode;
|
|
265
|
+
code: ErrorCode$1;
|
|
194
266
|
message: string;
|
|
195
267
|
}[];
|
|
196
268
|
}
|
|
197
269
|
/** Stable machine-readable error codes returned in API error bodies. */
|
|
198
|
-
declare const ERROR_CODES: {
|
|
270
|
+
declare const ERROR_CODES$1: {
|
|
199
271
|
readonly AUTH_REQUIRED: "AUTH_REQUIRED";
|
|
200
272
|
readonly AUTH_INVALID: "AUTH_INVALID";
|
|
201
273
|
readonly PERMISSION_DENIED: "PERMISSION_DENIED";
|
|
@@ -216,10 +288,10 @@ declare const ERROR_CODES: {
|
|
|
216
288
|
readonly INTEGRITY_CHECK_FAILED: "INTEGRITY_CHECK_FAILED";
|
|
217
289
|
readonly INTERNAL: "INTERNAL_ERROR";
|
|
218
290
|
};
|
|
219
|
-
type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
291
|
+
type ErrorCode$1 = (typeof ERROR_CODES$1)[keyof typeof ERROR_CODES$1];
|
|
220
292
|
interface ApiErrorBody {
|
|
221
293
|
error: {
|
|
222
|
-
code: ErrorCode;
|
|
294
|
+
code: ErrorCode$1;
|
|
223
295
|
message: string;
|
|
224
296
|
details?: unknown;
|
|
225
297
|
requestId?: string;
|
|
@@ -328,26 +400,26 @@ declare class FilesApi {
|
|
|
328
400
|
constructor(client: OmniCloudClient);
|
|
329
401
|
/** `folderId: null` = root; omit it to list every active file. */
|
|
330
402
|
list(query?: ListQuery): Promise<FilesPageDTO>;
|
|
331
|
-
get(id: string): Promise<FileDTO>;
|
|
403
|
+
get(id: string): Promise<FileDTO$1>;
|
|
332
404
|
versions(id: string): Promise<FileVersionDTO[]>;
|
|
333
405
|
/**
|
|
334
406
|
* Uploads a file with progress and retry support. Uses XMLHttpRequest when
|
|
335
407
|
* available (browsers) so progress and cancellation work; falls back to
|
|
336
408
|
* fetch elsewhere.
|
|
337
409
|
*/
|
|
338
|
-
upload(input: UploadInput, options?: UploadOptions): Promise<FileDTO>;
|
|
410
|
+
upload(input: UploadInput, options?: UploadOptions): Promise<FileDTO$1>;
|
|
339
411
|
private uploadOnce;
|
|
340
412
|
private uploadViaXhr;
|
|
341
413
|
/** Uploads a new version of an existing file. */
|
|
342
|
-
replace(id: string, input: UploadInput): Promise<FileDTO>;
|
|
414
|
+
replace(id: string, input: UploadInput): Promise<FileDTO$1>;
|
|
343
415
|
download(id: string, onProgress?: (p: DownloadProgress) => void): Promise<DownloadResult>;
|
|
344
416
|
/** URL suitable for direct download (anchor href). */
|
|
345
417
|
downloadUrl(id: string): string;
|
|
346
|
-
rename(id: string, name: string): Promise<FileDTO>;
|
|
347
|
-
star(id: string, starred?: boolean): Promise<FileDTO>;
|
|
348
|
-
move(id: string, folderId: string | null): Promise<FileDTO>;
|
|
349
|
-
trash(id: string): Promise<FileDTO>;
|
|
350
|
-
restore(id: string): Promise<FileDTO>;
|
|
418
|
+
rename(id: string, name: string): Promise<FileDTO$1>;
|
|
419
|
+
star(id: string, starred?: boolean): Promise<FileDTO$1>;
|
|
420
|
+
move(id: string, folderId: string | null): Promise<FileDTO$1>;
|
|
421
|
+
trash(id: string): Promise<FileDTO$1>;
|
|
422
|
+
restore(id: string): Promise<FileDTO$1>;
|
|
351
423
|
/** Permanently deletes a file and its Telegram objects. */
|
|
352
424
|
delete(id: string): Promise<void>;
|
|
353
425
|
/** Batch operation: trash | restore | delete | star | unstar | move. */
|
|
@@ -362,11 +434,11 @@ declare class FoldersApi {
|
|
|
362
434
|
parentId?: string | null;
|
|
363
435
|
}): Promise<FoldersPageDTO>;
|
|
364
436
|
/** The full active folder tree (for move dialogs). */
|
|
365
|
-
tree(): Promise<FolderDTO[]>;
|
|
366
|
-
create(name: string, parentId?: string | null): Promise<FolderDTO>;
|
|
367
|
-
rename(id: string, name: string): Promise<FolderDTO>;
|
|
368
|
-
star(id: string, starred?: boolean): Promise<FolderDTO>;
|
|
369
|
-
move(id: string, parentId: string | null): Promise<FolderDTO>;
|
|
437
|
+
tree(): Promise<FolderDTO$1[]>;
|
|
438
|
+
create(name: string, parentId?: string | null): Promise<FolderDTO$1>;
|
|
439
|
+
rename(id: string, name: string): Promise<FolderDTO$1>;
|
|
440
|
+
star(id: string, starred?: boolean): Promise<FolderDTO$1>;
|
|
441
|
+
move(id: string, parentId: string | null): Promise<FolderDTO$1>;
|
|
370
442
|
trash(id: string): Promise<FolderMutationResultDTO>;
|
|
371
443
|
restore(id: string): Promise<FolderMutationResultDTO>;
|
|
372
444
|
/** Permanently deletes the folder subtree and its Telegram objects. */
|
|
@@ -397,7 +469,7 @@ declare class StorageApi {
|
|
|
397
469
|
/** Read-only integrity scan; nothing is repaired or deleted. */
|
|
398
470
|
integrityCheck(options?: {
|
|
399
471
|
deep?: boolean;
|
|
400
|
-
}): Promise<IntegrityReportDTO>;
|
|
472
|
+
}): Promise<IntegrityReportDTO$1>;
|
|
401
473
|
/** Public server health (no authentication required). */
|
|
402
474
|
serverHealth(): Promise<HealthDTO>;
|
|
403
475
|
}
|
|
@@ -411,7 +483,7 @@ declare class SearchApi {
|
|
|
411
483
|
query(q: string, page?: {
|
|
412
484
|
page?: number;
|
|
413
485
|
limit?: number;
|
|
414
|
-
}): Promise<SearchResultDTO>;
|
|
486
|
+
}): Promise<SearchResultDTO$1>;
|
|
415
487
|
}
|
|
416
488
|
declare class RecentApi {
|
|
417
489
|
private readonly client;
|
|
@@ -419,7 +491,7 @@ declare class RecentApi {
|
|
|
419
491
|
list(page?: {
|
|
420
492
|
page?: number;
|
|
421
493
|
limit?: number;
|
|
422
|
-
}): Promise<RecentPageDTO>;
|
|
494
|
+
}): Promise<RecentPageDTO$1>;
|
|
423
495
|
}
|
|
424
496
|
declare class ActivityApi {
|
|
425
497
|
private readonly client;
|
|
@@ -444,5 +516,927 @@ declare class AuthApi {
|
|
|
444
516
|
|
|
445
517
|
/** Connection state of the underlying storage backend. */
|
|
446
518
|
type ConnectionState = "DISCONNECTED" | "CONNECTING" | "CONNECTED" | "RECONNECTING" | "ERROR" | "AUTH_REQUIRED";
|
|
519
|
+
interface FileDTO {
|
|
520
|
+
id: string;
|
|
521
|
+
name: string;
|
|
522
|
+
size: number;
|
|
523
|
+
mimeType: string;
|
|
524
|
+
sha256: string;
|
|
525
|
+
folderId: string | null;
|
|
526
|
+
starred: boolean;
|
|
527
|
+
trashed: boolean;
|
|
528
|
+
deletedAt: string | null;
|
|
529
|
+
versionCount: number;
|
|
530
|
+
currentVersionId: string | null;
|
|
531
|
+
createdAt: string;
|
|
532
|
+
updatedAt: string;
|
|
533
|
+
}
|
|
534
|
+
interface FolderDTO {
|
|
535
|
+
id: string;
|
|
536
|
+
name: string;
|
|
537
|
+
parentId: string | null;
|
|
538
|
+
starred: boolean;
|
|
539
|
+
trashed: boolean;
|
|
540
|
+
deletedAt: string | null;
|
|
541
|
+
createdAt: string;
|
|
542
|
+
updatedAt: string;
|
|
543
|
+
}
|
|
544
|
+
interface SearchResultDTO {
|
|
545
|
+
files: FileDTO[];
|
|
546
|
+
folders: FolderDTO[];
|
|
547
|
+
pagination: PaginationDTO;
|
|
548
|
+
}
|
|
549
|
+
interface PaginationDTO {
|
|
550
|
+
page: number;
|
|
551
|
+
limit: number;
|
|
552
|
+
total: number;
|
|
553
|
+
hasMore: boolean;
|
|
554
|
+
}
|
|
555
|
+
interface RecentItemDTO {
|
|
556
|
+
file: FileDTO;
|
|
557
|
+
lastAction: ActivityAction;
|
|
558
|
+
lastActionAt: string;
|
|
559
|
+
}
|
|
560
|
+
interface RecentPageDTO {
|
|
561
|
+
items: RecentItemDTO[];
|
|
562
|
+
pagination: PaginationDTO;
|
|
563
|
+
}
|
|
564
|
+
declare const ACTIVITY_ACTIONS: readonly ["upload", "download", "open", "rename", "move", "star", "unstar", "trash", "restore", "delete", "create_folder", "replace"];
|
|
565
|
+
type ActivityAction = (typeof ACTIVITY_ACTIONS)[number];
|
|
566
|
+
declare const RESOURCE_TYPES: readonly ["file", "folder", "storage"];
|
|
567
|
+
type ResourceType = (typeof RESOURCE_TYPES)[number];
|
|
568
|
+
interface IntegrityIssueDTO {
|
|
569
|
+
fileId: string;
|
|
570
|
+
name: string;
|
|
571
|
+
kind: "missing" | "size_mismatch" | "unreadable" | "hash_mismatch";
|
|
572
|
+
detail: string | null;
|
|
573
|
+
}
|
|
574
|
+
interface IntegrityReportDTO {
|
|
575
|
+
checkedAt: string;
|
|
576
|
+
filesChecked: number;
|
|
577
|
+
healthy: number;
|
|
578
|
+
missing: number;
|
|
579
|
+
inconsistent: number;
|
|
580
|
+
unreadable: number;
|
|
581
|
+
issues: IntegrityIssueDTO[];
|
|
582
|
+
durationMs: number;
|
|
583
|
+
}
|
|
584
|
+
/** Stable machine-readable error codes returned in API error bodies. */
|
|
585
|
+
declare const ERROR_CODES: {
|
|
586
|
+
readonly AUTH_REQUIRED: "AUTH_REQUIRED";
|
|
587
|
+
readonly AUTH_INVALID: "AUTH_INVALID";
|
|
588
|
+
readonly PERMISSION_DENIED: "PERMISSION_DENIED";
|
|
589
|
+
readonly INVALID_REQUEST: "INVALID_REQUEST";
|
|
590
|
+
readonly NOT_FOUND: "NOT_FOUND";
|
|
591
|
+
readonly FILE_NOT_FOUND: "FILE_NOT_FOUND";
|
|
592
|
+
readonly FOLDER_NOT_FOUND: "FOLDER_NOT_FOUND";
|
|
593
|
+
readonly CONFLICT: "CONFLICT";
|
|
594
|
+
readonly PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE";
|
|
595
|
+
readonly RATE_LIMITED: "RATE_LIMITED";
|
|
596
|
+
readonly STORAGE_NOT_INITIALIZED: "STORAGE_NOT_INITIALIZED";
|
|
597
|
+
readonly STORAGE_UNAVAILABLE: "STORAGE_UNAVAILABLE";
|
|
598
|
+
readonly TELEGRAM_AUTH_REQUIRED: "TELEGRAM_AUTH_REQUIRED";
|
|
599
|
+
readonly TELEGRAM_CONNECTION_FAILED: "TELEGRAM_CONNECTION_FAILED";
|
|
600
|
+
readonly TELEGRAM_FILE_NOT_FOUND: "TELEGRAM_FILE_NOT_FOUND";
|
|
601
|
+
readonly UPLOAD_FAILED: "UPLOAD_FAILED";
|
|
602
|
+
readonly DOWNLOAD_FAILED: "DOWNLOAD_FAILED";
|
|
603
|
+
readonly INTEGRITY_CHECK_FAILED: "INTEGRITY_CHECK_FAILED";
|
|
604
|
+
readonly INTERNAL: "INTERNAL_ERROR";
|
|
605
|
+
};
|
|
606
|
+
type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Base class for all domain errors. The API maps these to structured HTTP
|
|
610
|
+
* responses; everything else becomes a 500.
|
|
611
|
+
*/
|
|
612
|
+
declare class DomainError extends Error {
|
|
613
|
+
readonly code: ErrorCode;
|
|
614
|
+
readonly status: number;
|
|
615
|
+
readonly details?: unknown;
|
|
616
|
+
constructor(code: ErrorCode, status: number, message: string, details?: unknown);
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Wraps an arbitrary provider failure as an UploadFailedError (the default
|
|
620
|
+
* storage-operation error), preserving domain errors untouched.
|
|
621
|
+
*/
|
|
622
|
+
declare function mapProviderError(message: string, error: unknown): DomainError;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Domain records. Repository implementations (e.g. the Prisma layer) map
|
|
626
|
+
* their persistence models onto these records; the rest of the application
|
|
627
|
+
* only ever works with them.
|
|
628
|
+
*
|
|
629
|
+
* Telegram identifiers are represented as strings/numbers that fit in
|
|
630
|
+
* JavaScript's safe integer range; the persistence layer converts as needed.
|
|
631
|
+
*/
|
|
632
|
+
|
|
633
|
+
interface UserRecord {
|
|
634
|
+
id: string;
|
|
635
|
+
telegramUserId: string;
|
|
636
|
+
username: string | null;
|
|
637
|
+
firstName: string | null;
|
|
638
|
+
lastName: string | null;
|
|
639
|
+
phone: string | null;
|
|
640
|
+
createdAt: Date;
|
|
641
|
+
}
|
|
642
|
+
interface TelegramSessionRecord {
|
|
643
|
+
userId: string;
|
|
644
|
+
stringSession: string;
|
|
645
|
+
}
|
|
646
|
+
interface StorageRecord {
|
|
647
|
+
id: string;
|
|
648
|
+
userId: string;
|
|
649
|
+
provider: string;
|
|
650
|
+
title: string;
|
|
651
|
+
telegramChatId: string;
|
|
652
|
+
telegramAccessHash: string;
|
|
653
|
+
createdAt: Date;
|
|
654
|
+
}
|
|
655
|
+
interface FolderRecord {
|
|
656
|
+
id: string;
|
|
657
|
+
userId: string;
|
|
658
|
+
parentId: string | null;
|
|
659
|
+
name: string;
|
|
660
|
+
starred: boolean;
|
|
661
|
+
/** Soft-delete marker (null = active). */
|
|
662
|
+
deletedAt: Date | null;
|
|
663
|
+
/**
|
|
664
|
+
* Groups everything moved to the Trash by one operation, so restoring a
|
|
665
|
+
* folder restores exactly what it took (and leaves separately-trashed
|
|
666
|
+
* items alone). Null for items trashed individually.
|
|
667
|
+
*/
|
|
668
|
+
trashBatchId: string | null;
|
|
669
|
+
createdAt: Date;
|
|
670
|
+
updatedAt: Date;
|
|
671
|
+
}
|
|
672
|
+
interface FileRecord {
|
|
673
|
+
id: string;
|
|
674
|
+
userId: string;
|
|
675
|
+
folderId: string | null;
|
|
676
|
+
name: string;
|
|
677
|
+
size: number;
|
|
678
|
+
mimeType: string;
|
|
679
|
+
sha256: string;
|
|
680
|
+
telegramMessageId: number;
|
|
681
|
+
starred: boolean;
|
|
682
|
+
/** Soft-delete marker (null = active). */
|
|
683
|
+
deletedAt: Date | null;
|
|
684
|
+
/** See FolderRecord.trashBatchId. */
|
|
685
|
+
trashBatchId: string | null;
|
|
686
|
+
/** Current version row, if versioning has been initialized for this file. */
|
|
687
|
+
currentVersionId: string | null;
|
|
688
|
+
versionCount: number;
|
|
689
|
+
createdAt: Date;
|
|
690
|
+
updatedAt: Date;
|
|
691
|
+
}
|
|
692
|
+
interface FileVersionRecord {
|
|
693
|
+
id: string;
|
|
694
|
+
fileId: string;
|
|
695
|
+
userId: string;
|
|
696
|
+
versionNumber: number;
|
|
697
|
+
size: number;
|
|
698
|
+
mimeType: string;
|
|
699
|
+
sha256: string;
|
|
700
|
+
telegramMessageId: number;
|
|
701
|
+
createdAt: Date;
|
|
702
|
+
}
|
|
703
|
+
interface ActivityEventRecord {
|
|
704
|
+
id: string;
|
|
705
|
+
userId: string;
|
|
706
|
+
action: ActivityAction;
|
|
707
|
+
resourceType: ResourceType;
|
|
708
|
+
resourceId: string;
|
|
709
|
+
resourceName: string | null;
|
|
710
|
+
metadata: Record<string, unknown> | null;
|
|
711
|
+
createdAt: Date;
|
|
712
|
+
}
|
|
713
|
+
/** Resolved, repository-ready item query (search parser output resolved). */
|
|
714
|
+
interface ItemQuery {
|
|
715
|
+
/** Restrict to a folder (null = root). Undefined = any folder. */
|
|
716
|
+
folderId?: string | null;
|
|
717
|
+
/** Restrict to a set of folder ids (used for `folder:Name` filters). */
|
|
718
|
+
folderIds?: string[];
|
|
719
|
+
nameContains?: string;
|
|
720
|
+
/** MIME matchers: exact values or prefixes ending in "/". */
|
|
721
|
+
mimeMatchers?: readonly string[];
|
|
722
|
+
ext?: string;
|
|
723
|
+
starred?: boolean;
|
|
724
|
+
/** false = active only, true = trashed only, undefined = both. */
|
|
725
|
+
trashed?: boolean;
|
|
726
|
+
minSize?: number;
|
|
727
|
+
maxSize?: number;
|
|
728
|
+
from?: Date;
|
|
729
|
+
to?: Date;
|
|
730
|
+
sort?: SortField;
|
|
731
|
+
order?: SortOrder;
|
|
732
|
+
}
|
|
733
|
+
interface PageRequest {
|
|
734
|
+
page: number;
|
|
735
|
+
limit: number;
|
|
736
|
+
}
|
|
737
|
+
interface Paged<T> {
|
|
738
|
+
items: T[];
|
|
739
|
+
total: number;
|
|
740
|
+
}
|
|
741
|
+
interface FileTypeBucket {
|
|
742
|
+
category: string;
|
|
743
|
+
bytes: number;
|
|
744
|
+
count: number;
|
|
745
|
+
}
|
|
746
|
+
interface StorageStats {
|
|
747
|
+
fileCount: number;
|
|
748
|
+
folderCount: number;
|
|
749
|
+
totalBytes: number;
|
|
750
|
+
trashBytes: number;
|
|
751
|
+
trashFileCount: number;
|
|
752
|
+
starredCount: number;
|
|
753
|
+
byType: FileTypeBucket[];
|
|
754
|
+
largestFiles: FileRecord[];
|
|
755
|
+
/** Optional quota ceiling (null = unlimited, the v0.2 default). */
|
|
756
|
+
quotaBytes: number | null;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Repository interfaces. The application depends on these, not on a specific
|
|
761
|
+
* database — the Prisma implementation lives in @omnicloud/database, and
|
|
762
|
+
* tests use in-memory implementations.
|
|
763
|
+
*/
|
|
764
|
+
interface UserRepository {
|
|
765
|
+
findById(id: string): Promise<UserRecord | null>;
|
|
766
|
+
findByTelegramId(telegramUserId: string): Promise<UserRecord | null>;
|
|
767
|
+
upsertFromTelegram(input: {
|
|
768
|
+
telegramUserId: string;
|
|
769
|
+
username: string | null;
|
|
770
|
+
firstName: string | null;
|
|
771
|
+
lastName: string | null;
|
|
772
|
+
phone: string | null;
|
|
773
|
+
}): Promise<UserRecord>;
|
|
774
|
+
}
|
|
775
|
+
interface SessionRepository {
|
|
776
|
+
get(userId: string): Promise<TelegramSessionRecord | null>;
|
|
777
|
+
save(userId: string, stringSession: string): Promise<void>;
|
|
778
|
+
delete(userId: string): Promise<void>;
|
|
779
|
+
}
|
|
780
|
+
interface StorageRepository {
|
|
781
|
+
findByUserAndProvider(userId: string, provider: string): Promise<StorageRecord | null>;
|
|
782
|
+
create(input: {
|
|
783
|
+
userId: string;
|
|
784
|
+
provider: string;
|
|
785
|
+
title: string;
|
|
786
|
+
telegramChatId: string;
|
|
787
|
+
telegramAccessHash: string;
|
|
788
|
+
}): Promise<StorageRecord>;
|
|
789
|
+
}
|
|
790
|
+
interface FolderCreateInput {
|
|
791
|
+
userId: string;
|
|
792
|
+
parentId: string | null;
|
|
793
|
+
name: string;
|
|
794
|
+
}
|
|
795
|
+
interface FolderRepository {
|
|
796
|
+
create(input: FolderCreateInput): Promise<FolderRecord>;
|
|
797
|
+
findById(id: string): Promise<FolderRecord | null>;
|
|
798
|
+
/** Every folder belonging to the user (used for trees and cascade logic). */
|
|
799
|
+
listByUser(userId: string): Promise<FolderRecord[]>;
|
|
800
|
+
listChildren(userId: string, parentId: string | null): Promise<FolderRecord[]>;
|
|
801
|
+
/** Filtered, sorted, paginated listing. */
|
|
802
|
+
query(userId: string, query: ItemQuery, page: PageRequest): Promise<Paged<FolderRecord>>;
|
|
803
|
+
/** Folder ids matching a name substring (used to resolve `folder:` filters). */
|
|
804
|
+
findIdsByName(userId: string, name: string): Promise<string[]>;
|
|
805
|
+
update(id: string, patch: {
|
|
806
|
+
name?: string;
|
|
807
|
+
parentId?: string | null;
|
|
808
|
+
starred?: boolean;
|
|
809
|
+
deletedAt?: Date | null;
|
|
810
|
+
trashBatchId?: string | null;
|
|
811
|
+
}): Promise<FolderRecord>;
|
|
812
|
+
/** Bulk trash/restore/star without touching files. */
|
|
813
|
+
updateMany(ids: string[], patch: {
|
|
814
|
+
starred?: boolean;
|
|
815
|
+
deletedAt?: Date | null;
|
|
816
|
+
trashBatchId?: string | null;
|
|
817
|
+
}): Promise<number>;
|
|
818
|
+
deleteMany(ids: string[]): Promise<void>;
|
|
819
|
+
countByUser(userId: string): Promise<number>;
|
|
820
|
+
}
|
|
821
|
+
interface FileCreateInput {
|
|
822
|
+
userId: string;
|
|
823
|
+
folderId: string | null;
|
|
824
|
+
name: string;
|
|
825
|
+
size: number;
|
|
826
|
+
mimeType: string;
|
|
827
|
+
sha256: string;
|
|
828
|
+
telegramMessageId: number;
|
|
829
|
+
}
|
|
830
|
+
interface FileRepository {
|
|
831
|
+
create(input: FileCreateInput): Promise<FileRecord>;
|
|
832
|
+
findById(id: string): Promise<FileRecord | null>;
|
|
833
|
+
/** Active files directly inside a folder (null = root). */
|
|
834
|
+
listByFolder(userId: string, folderId: string | null): Promise<FileRecord[]>;
|
|
835
|
+
listByUser(userId: string): Promise<FileRecord[]>;
|
|
836
|
+
listByIds(userId: string, ids: string[]): Promise<FileRecord[]>;
|
|
837
|
+
query(userId: string, query: ItemQuery, page: PageRequest): Promise<Paged<FileRecord>>;
|
|
838
|
+
update(id: string, patch: {
|
|
839
|
+
name?: string;
|
|
840
|
+
folderId?: string | null;
|
|
841
|
+
starred?: boolean;
|
|
842
|
+
deletedAt?: Date | null;
|
|
843
|
+
trashBatchId?: string | null;
|
|
844
|
+
size?: number;
|
|
845
|
+
mimeType?: string;
|
|
846
|
+
sha256?: string;
|
|
847
|
+
telegramMessageId?: number;
|
|
848
|
+
currentVersionId?: string | null;
|
|
849
|
+
versionCount?: number;
|
|
850
|
+
}): Promise<FileRecord>;
|
|
851
|
+
updateMany(ids: string[], patch: {
|
|
852
|
+
folderId?: string | null;
|
|
853
|
+
starred?: boolean;
|
|
854
|
+
deletedAt?: Date | null;
|
|
855
|
+
trashBatchId?: string | null;
|
|
856
|
+
}): Promise<number>;
|
|
857
|
+
/** Aggregate counters used by the storage dashboard. */
|
|
858
|
+
statsByUser(userId: string): Promise<{
|
|
859
|
+
fileCount: number;
|
|
860
|
+
folderCount: number;
|
|
861
|
+
totalBytes: number;
|
|
862
|
+
trashBytes: number;
|
|
863
|
+
trashFileCount: number;
|
|
864
|
+
starredCount: number;
|
|
865
|
+
}>;
|
|
866
|
+
deleteMany(ids: string[]): Promise<void>;
|
|
867
|
+
createVersion(input: {
|
|
868
|
+
fileId: string;
|
|
869
|
+
userId: string;
|
|
870
|
+
size: number;
|
|
871
|
+
mimeType: string;
|
|
872
|
+
sha256: string;
|
|
873
|
+
telegramMessageId: number;
|
|
874
|
+
}): Promise<FileVersionRecord>;
|
|
875
|
+
listVersions(fileId: string): Promise<FileVersionRecord[]>;
|
|
876
|
+
findVersionById(versionId: string): Promise<FileVersionRecord | null>;
|
|
877
|
+
countVersions(fileId: string): Promise<number>;
|
|
878
|
+
deleteVersionsByFileIds(fileIds: string[]): Promise<void>;
|
|
879
|
+
}
|
|
880
|
+
interface ActivityRepository {
|
|
881
|
+
record(input: {
|
|
882
|
+
userId: string;
|
|
883
|
+
action: ActivityAction;
|
|
884
|
+
resourceType: ResourceType;
|
|
885
|
+
resourceId: string;
|
|
886
|
+
resourceName?: string | null;
|
|
887
|
+
metadata?: Record<string, unknown> | null;
|
|
888
|
+
}): Promise<void>;
|
|
889
|
+
/** Newest-first activity for a user. */
|
|
890
|
+
list(userId: string, page: PageRequest): Promise<Paged<ActivityEventRecord>>;
|
|
891
|
+
/**
|
|
892
|
+
* Most recent distinct files for the given actions, newest first. Only
|
|
893
|
+
* events whose action is listed are considered, so a file whose latest
|
|
894
|
+
* event is (say) a star still surfaces via its last meaningful action.
|
|
895
|
+
*/
|
|
896
|
+
recentFiles(userId: string, actions: readonly ActivityAction[], limit: number): Promise<ActivityEventRecord[]>;
|
|
897
|
+
countByUser(userId: string): Promise<number>;
|
|
898
|
+
/** Housekeeping: drop events older than the retention window. */
|
|
899
|
+
pruneOlderThan(cutoff: Date): Promise<number>;
|
|
900
|
+
}
|
|
901
|
+
interface Repos {
|
|
902
|
+
users: UserRepository;
|
|
903
|
+
sessions: SessionRepository;
|
|
904
|
+
storages: StorageRepository;
|
|
905
|
+
folders: FolderRepository;
|
|
906
|
+
files: FileRepository;
|
|
907
|
+
activity: ActivityRepository;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Generic storage abstraction. The application must never depend on
|
|
912
|
+
* Telegram-specific details — it talks to a StorageProvider.
|
|
913
|
+
*
|
|
914
|
+
* v0.2 adds streaming, progress reporting, cancellation and health checks
|
|
915
|
+
* while keeping the abstraction provider-agnostic.
|
|
916
|
+
*/
|
|
917
|
+
/** Reference to an object inside the backing store (opaque to callers). */
|
|
918
|
+
interface StoredRef {
|
|
919
|
+
messageId: string;
|
|
920
|
+
}
|
|
921
|
+
interface StoredObject extends StoredRef {
|
|
922
|
+
name: string;
|
|
923
|
+
size: number;
|
|
924
|
+
mimeType: string;
|
|
925
|
+
}
|
|
926
|
+
/** Transfer progress emitted during upload/download. */
|
|
927
|
+
interface TransferProgress {
|
|
928
|
+
/** Bytes transferred so far. */
|
|
929
|
+
transferred: number;
|
|
930
|
+
/** Total bytes, when known upfront. */
|
|
931
|
+
total: number | null;
|
|
932
|
+
/** 0–100 when total is known, otherwise null. */
|
|
933
|
+
percent: number | null;
|
|
934
|
+
}
|
|
935
|
+
interface TransferControl {
|
|
936
|
+
/** Aborted when the caller cancels the operation. */
|
|
937
|
+
signal?: AbortSignal;
|
|
938
|
+
onProgress?: (progress: TransferProgress) => void;
|
|
939
|
+
}
|
|
940
|
+
/** Upload input. `data` is a Buffer; `stream` is used for large files. */
|
|
941
|
+
interface StorageUploadInput {
|
|
942
|
+
name: string;
|
|
943
|
+
mimeType: string;
|
|
944
|
+
/** Whole-object buffer (small files). */
|
|
945
|
+
data?: Buffer;
|
|
946
|
+
/** Streaming source (large files). Either `data` or `stream` is required. */
|
|
947
|
+
stream?: Readable;
|
|
948
|
+
/** Total byte length, required when streaming. */
|
|
949
|
+
size?: number;
|
|
950
|
+
}
|
|
951
|
+
interface StorageHealth {
|
|
952
|
+
/** Reachable and usable. */
|
|
953
|
+
healthy: boolean;
|
|
954
|
+
/** Round-trip latency of the probe in milliseconds, when measured. */
|
|
955
|
+
latencyMs: number | null;
|
|
956
|
+
message: string | null;
|
|
957
|
+
/** Name of the storage channel/target, when available. */
|
|
958
|
+
targetTitle: string | null;
|
|
959
|
+
}
|
|
960
|
+
interface StorageProvider {
|
|
961
|
+
readonly name: string;
|
|
962
|
+
/**
|
|
963
|
+
* Uploads an object and returns the stored reference. Reports progress and
|
|
964
|
+
* honors `control.signal` for cancellation.
|
|
965
|
+
*/
|
|
966
|
+
put(input: StorageUploadInput, control?: TransferControl): Promise<StoredObject>;
|
|
967
|
+
/** Downloads the object's content as a Buffer. */
|
|
968
|
+
get(ref: StoredRef, control?: TransferControl): Promise<Buffer>;
|
|
969
|
+
/** Opens a stream for the object (large-file friendly). */
|
|
970
|
+
getStream(ref: StoredRef, control?: TransferControl): Promise<Readable>;
|
|
971
|
+
/** Deletes the object. Deleting an already-missing object must not throw. */
|
|
972
|
+
delete(ref: StoredRef): Promise<void>;
|
|
973
|
+
exists(ref: StoredRef): Promise<boolean>;
|
|
974
|
+
stat(ref: StoredRef): Promise<StoredObject | null>;
|
|
975
|
+
/** Validates that the backing store is reachable and usable. */
|
|
976
|
+
healthCheck(): Promise<StorageHealth>;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
declare function sha256Hex(data: Uint8Array): string;
|
|
980
|
+
|
|
981
|
+
interface EngineUploadResult {
|
|
982
|
+
stored: StoredObject;
|
|
983
|
+
sha256: string;
|
|
984
|
+
size: number;
|
|
985
|
+
}
|
|
986
|
+
interface EngineRetryPolicy {
|
|
987
|
+
/** Total attempts, including the first. */
|
|
988
|
+
attempts: number;
|
|
989
|
+
/** Base delay in ms; doubles per retry. */
|
|
990
|
+
baseDelayMs: number;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Sits between the application and the raw StorageProvider and adds the
|
|
994
|
+
* cross-cutting guarantees: SHA-256 integrity, streaming, progress reporting,
|
|
995
|
+
* cancellation and bounded retries.
|
|
996
|
+
*
|
|
997
|
+
* The active provider is chosen per user by the host application (each user
|
|
998
|
+
* has their own Telegram storage channel).
|
|
999
|
+
*/
|
|
1000
|
+
declare class StorageEngine {
|
|
1001
|
+
private readonly provider;
|
|
1002
|
+
private readonly retryPolicy;
|
|
1003
|
+
constructor(provider: StorageProvider, retryPolicy?: EngineRetryPolicy);
|
|
1004
|
+
get providerName(): string;
|
|
1005
|
+
/**
|
|
1006
|
+
* Uploads an object, computing its SHA-256 as it goes and reporting
|
|
1007
|
+
* progress. Retries transient failures with exponential backoff.
|
|
1008
|
+
*/
|
|
1009
|
+
upload(input: StorageUploadInput, control?: TransferControl): Promise<EngineUploadResult>;
|
|
1010
|
+
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
|
+
}>;
|
|
1016
|
+
remove(ref: StoredRef): Promise<void>;
|
|
1017
|
+
exists(ref: StoredRef): Promise<boolean>;
|
|
1018
|
+
stat(ref: StoredRef): Promise<StoredObject | null>;
|
|
1019
|
+
health(): Promise<StorageHealth>;
|
|
1020
|
+
verifyIntegrity(data: Buffer, expectedSha256: string): Promise<boolean>;
|
|
1021
|
+
/** Materializes an upload input so the checksum can be computed. */
|
|
1022
|
+
private readInput;
|
|
1023
|
+
private withRetry;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
interface RecordActivityInput {
|
|
1027
|
+
userId: string;
|
|
1028
|
+
action: ActivityAction;
|
|
1029
|
+
resourceType: ResourceType;
|
|
1030
|
+
resourceId: string;
|
|
1031
|
+
resourceName?: string | null;
|
|
1032
|
+
metadata?: Record<string, unknown> | null;
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* The narrow interface other services depend on for activity logging, so a
|
|
1036
|
+
* no-op recorder can be substituted in tests and activity failures never
|
|
1037
|
+
* break the operation being logged.
|
|
1038
|
+
*/
|
|
1039
|
+
interface ActivityRecorder {
|
|
1040
|
+
record(input: RecordActivityInput): Promise<void>;
|
|
1041
|
+
}
|
|
1042
|
+
/** Activity log with best-effort recording and retention pruning. */
|
|
1043
|
+
declare class ActivityService implements ActivityRecorder {
|
|
1044
|
+
private readonly activity;
|
|
1045
|
+
/** Days to retain events; older rows are pruned on demand. */
|
|
1046
|
+
private readonly retentionDays;
|
|
1047
|
+
constructor(activity: ActivityRepository,
|
|
1048
|
+
/** Days to retain events; older rows are pruned on demand. */
|
|
1049
|
+
retentionDays?: number);
|
|
1050
|
+
/**
|
|
1051
|
+
* Records an event. Never throws — a logging failure must not fail the
|
|
1052
|
+
* user-facing operation that produced it.
|
|
1053
|
+
*/
|
|
1054
|
+
record(input: RecordActivityInput): Promise<void>;
|
|
1055
|
+
list(userId: string, page: PageRequest): Promise<Paged<ActivityEventRecord>>;
|
|
1056
|
+
/** Most recent distinct files for the given actions, for the Recent view. */
|
|
1057
|
+
recentFiles(userId: string, actions: readonly ActivityAction[], limit: number): Promise<ActivityEventRecord[]>;
|
|
1058
|
+
prune(): Promise<number>;
|
|
1059
|
+
}
|
|
1060
|
+
/** A recorder that discards events (used where activity is not wired up). */
|
|
1061
|
+
declare const noopActivityRecorder: ActivityRecorder;
|
|
1062
|
+
|
|
1063
|
+
interface FileDownload {
|
|
1064
|
+
record: FileRecord;
|
|
1065
|
+
data: Buffer;
|
|
1066
|
+
integrityVerified: boolean;
|
|
1067
|
+
}
|
|
1068
|
+
type EngineResolver = (userId: string) => Promise<StorageEngine>;
|
|
1069
|
+
interface FileUploadInput {
|
|
1070
|
+
folderId: string | null;
|
|
1071
|
+
name: string;
|
|
1072
|
+
data: Buffer;
|
|
1073
|
+
/** When set, uploads a new version of this file instead of creating one. */
|
|
1074
|
+
replaceFileId?: string;
|
|
1075
|
+
/** Progress callback forwarded from the transport layer. */
|
|
1076
|
+
onProgress?: (progress: TransferProgress) => void;
|
|
1077
|
+
signal?: AbortSignal;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* File metadata operations. Every method verifies ownership: records
|
|
1081
|
+
* belonging to other users are reported as missing.
|
|
1082
|
+
*
|
|
1083
|
+
* Reliability rules honored here:
|
|
1084
|
+
* - metadata is written only after the storage upload succeeds;
|
|
1085
|
+
* - permanent deletion removes the remote object before the metadata;
|
|
1086
|
+
* - client-supplied ownership is never trusted (userId is server-derived).
|
|
1087
|
+
*/
|
|
1088
|
+
declare class FileService {
|
|
1089
|
+
private readonly files;
|
|
1090
|
+
private readonly folders;
|
|
1091
|
+
private readonly engineFor;
|
|
1092
|
+
private readonly activity;
|
|
1093
|
+
constructor(files: FileRepository, folders: FolderRepository, engineFor: EngineResolver, activity?: ActivityRecorder);
|
|
1094
|
+
upload(userId: string, input: FileUploadInput): Promise<FileRecord>;
|
|
1095
|
+
/** Uploads a new version of an existing file and makes it current. */
|
|
1096
|
+
private replaceVersion;
|
|
1097
|
+
list(userId: string, folderId: string | null): Promise<FileRecord[]>;
|
|
1098
|
+
query(userId: string, input: ListQuery, page: PageRequest): Promise<Paged<FileRecord>>;
|
|
1099
|
+
get(userId: string, id: string): Promise<FileRecord>;
|
|
1100
|
+
/** Like get(), but rejects trashed files (for download/open). */
|
|
1101
|
+
getActive(userId: string, id: string): Promise<FileRecord>;
|
|
1102
|
+
listVersions(userId: string, id: string): Promise<FileVersionRecord[]>;
|
|
1103
|
+
rename(userId: string, id: string, name: string): Promise<FileRecord>;
|
|
1104
|
+
move(userId: string, id: string, folderId: string | null): Promise<FileRecord>;
|
|
1105
|
+
setStarred(userId: string, id: string, starred: boolean): Promise<FileRecord>;
|
|
1106
|
+
/**
|
|
1107
|
+
* Moves a file to Trash (soft delete). The remote object is untouched, so
|
|
1108
|
+
* restore is lossless.
|
|
1109
|
+
*/
|
|
1110
|
+
trash(userId: string, id: string): Promise<FileRecord>;
|
|
1111
|
+
/** Restores a trashed file to its previous folder (or root). */
|
|
1112
|
+
restore(userId: string, id: string): Promise<FileRecord>;
|
|
1113
|
+
/**
|
|
1114
|
+
* Permanently deletes a file: the Telegram object is removed first, then the
|
|
1115
|
+
* metadata. If the remote delete fails we keep the metadata so the user can
|
|
1116
|
+
* retry, rather than silently orphaning the storage object.
|
|
1117
|
+
*/
|
|
1118
|
+
deletePermanently(userId: string, id: string): Promise<void>;
|
|
1119
|
+
/**
|
|
1120
|
+
* v0.1-compatible hard delete used by the current API: permanently removes
|
|
1121
|
+
* the file. Retained so existing clients keep working.
|
|
1122
|
+
*/
|
|
1123
|
+
delete(userId: string, id: string): Promise<void>;
|
|
1124
|
+
download(userId: string, id: string, control?: TransferControl): Promise<FileDownload>;
|
|
1125
|
+
/** Records an "open" event (the UI opening the details panel, say). */
|
|
1126
|
+
touch(userId: string, id: string, action?: "open"): Promise<void>;
|
|
1127
|
+
/**
|
|
1128
|
+
* Applies an operation to many files, collecting per-item failures instead
|
|
1129
|
+
* of aborting the whole batch.
|
|
1130
|
+
*/
|
|
1131
|
+
batch(userId: string, ids: string[], operation: "trash" | "restore" | "delete" | "star" | "unstar" | "move", options?: {
|
|
1132
|
+
folderId?: string | null;
|
|
1133
|
+
}): Promise<{
|
|
1134
|
+
requested: number;
|
|
1135
|
+
succeeded: number;
|
|
1136
|
+
failed: number;
|
|
1137
|
+
errors: {
|
|
1138
|
+
id: string;
|
|
1139
|
+
message: string;
|
|
1140
|
+
}[];
|
|
1141
|
+
}>;
|
|
1142
|
+
private assertFolder;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
interface FolderMutationResult {
|
|
1146
|
+
affectedFolders: number;
|
|
1147
|
+
affectedFiles: number;
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Folder lifecycle (v0.2):
|
|
1151
|
+
*
|
|
1152
|
+
* - Folders are virtual OmniCloud objects with a parent-child hierarchy.
|
|
1153
|
+
* - Trashing a folder trashes its whole subtree (folders + files) without
|
|
1154
|
+
* touching Telegram, so restore is lossless.
|
|
1155
|
+
* - Restoring a folder restores only the nodes that were trashed together
|
|
1156
|
+
* with it; anything the user trashed separately stays in the Trash.
|
|
1157
|
+
* - Permanent deletion removes remote objects first, then metadata.
|
|
1158
|
+
*/
|
|
1159
|
+
declare class FolderService {
|
|
1160
|
+
private readonly folders;
|
|
1161
|
+
private readonly files;
|
|
1162
|
+
private readonly engineFor;
|
|
1163
|
+
private readonly activity;
|
|
1164
|
+
constructor(folders: FolderRepository, files: FileRepository, engineFor: EngineResolver, activity?: ActivityRecorder);
|
|
1165
|
+
create(userId: string, input: {
|
|
1166
|
+
name: string;
|
|
1167
|
+
parentId: string | null;
|
|
1168
|
+
}): Promise<FolderRecord>;
|
|
1169
|
+
/** Active folders directly inside a folder (null = root). */
|
|
1170
|
+
listChildren(userId: string, parentId: string | null): Promise<FolderRecord[]>;
|
|
1171
|
+
query(userId: string, input: ListQuery, page: PageRequest): Promise<Paged<FolderRecord>>;
|
|
1172
|
+
/** Every active folder for the user (used to build trees). */
|
|
1173
|
+
tree(userId: string): Promise<FolderRecord[]>;
|
|
1174
|
+
get(userId: string, id: string): Promise<FolderRecord>;
|
|
1175
|
+
rename(userId: string, id: string, name: string): Promise<FolderRecord>;
|
|
1176
|
+
move(userId: string, id: string, newParentId: string | null): Promise<FolderRecord>;
|
|
1177
|
+
setStarred(userId: string, id: string, starred: boolean): Promise<FolderRecord>;
|
|
1178
|
+
/**
|
|
1179
|
+
* Moves a folder and its entire subtree to the Trash. Nothing is deleted
|
|
1180
|
+
* from Telegram, so restore is lossless.
|
|
1181
|
+
*/
|
|
1182
|
+
trash(userId: string, id: string): Promise<FolderMutationResult>;
|
|
1183
|
+
/**
|
|
1184
|
+
* Restores a folder subtree. Only nodes trashed at the same instant as the
|
|
1185
|
+
* folder itself are restored, so items the user trashed separately stay put.
|
|
1186
|
+
*/
|
|
1187
|
+
restore(userId: string, id: string): Promise<FolderMutationResult>;
|
|
1188
|
+
/**
|
|
1189
|
+
* Permanently deletes a folder subtree: remote objects first, then
|
|
1190
|
+
* metadata. Files whose remote delete fails are left in the Trash so the
|
|
1191
|
+
* user can retry rather than losing data silently.
|
|
1192
|
+
*/
|
|
1193
|
+
deletePermanently(userId: string, id: string): Promise<FolderMutationResult>;
|
|
1194
|
+
/**
|
|
1195
|
+
* v0.1-compatible recursive delete. Now routes through the v0.2 permanent
|
|
1196
|
+
* delete so remote cleanup and orphan prevention are consistent.
|
|
1197
|
+
*/
|
|
1198
|
+
delete(userId: string, id: string): Promise<FolderMutationResult>;
|
|
1199
|
+
/** The folder plus every descendant (BFS), optionally including trashed. */
|
|
1200
|
+
private collectSubtree;
|
|
1201
|
+
/** Ids of files inside the given folders that are not already trashed. */
|
|
1202
|
+
private collectFileIds;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
interface SearchResult {
|
|
1206
|
+
files: FileRecord[];
|
|
1207
|
+
folders: FolderRecord[];
|
|
1208
|
+
pagination: PaginationDTO;
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* PostgreSQL-backed search (no Elasticsearch, per the v0.2 scope).
|
|
1212
|
+
*
|
|
1213
|
+
* The user query is parsed into structured filters (`type:`, `size:`,
|
|
1214
|
+
* `folder:`, …) and evaluated by the repository layer, so results respect
|
|
1215
|
+
* ownership and stay safely parameterized.
|
|
1216
|
+
*/
|
|
1217
|
+
declare class SearchService {
|
|
1218
|
+
private readonly files;
|
|
1219
|
+
private readonly folders;
|
|
1220
|
+
constructor(files: FileRepository, folders: FolderRepository);
|
|
1221
|
+
search(userId: string, rawQuery: string, page: PageRequest, overrides?: ListQuery): Promise<SearchResult>;
|
|
1222
|
+
/** Convenience wrapper returning the shared DTO shape. */
|
|
1223
|
+
searchDTO(userId: string, rawQuery: string, page: PageRequest): Promise<Omit<SearchResultDTO, "files" | "folders"> & SearchResult>;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Storage dashboard statistics, computed from PostgreSQL metadata only —
|
|
1228
|
+
* no Telegram round-trips, so the page is fast and works offline.
|
|
1229
|
+
*/
|
|
1230
|
+
declare class StatsService {
|
|
1231
|
+
private readonly files;
|
|
1232
|
+
private readonly folders;
|
|
1233
|
+
constructor(files: FileRepository, folders: FolderRepository);
|
|
1234
|
+
stats(userId: string, quotaBytes?: number | null): Promise<StorageStats>;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
interface TrashListing {
|
|
1238
|
+
files: FileRecord[];
|
|
1239
|
+
folders: FolderRecord[];
|
|
1240
|
+
pagination: PaginationDTO;
|
|
1241
|
+
}
|
|
1242
|
+
interface EmptyTrashResult {
|
|
1243
|
+
deletedFiles: number;
|
|
1244
|
+
deletedFolders: number;
|
|
1245
|
+
failedFiles: number;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Trash is a virtual view over soft-deleted rows. Listing shows only the
|
|
1249
|
+
* explicitly trashed items; emptying removes their remote objects before the
|
|
1250
|
+
* metadata, and reports failures instead of hiding them.
|
|
1251
|
+
*/
|
|
1252
|
+
declare class TrashService {
|
|
1253
|
+
private readonly files;
|
|
1254
|
+
private readonly folders;
|
|
1255
|
+
private readonly engineFor;
|
|
1256
|
+
constructor(files: FileRepository, folders: FolderRepository, engineFor: EngineResolver);
|
|
1257
|
+
list(userId: string, page: PageRequest, extra?: ListQuery): Promise<TrashListing>;
|
|
1258
|
+
/**
|
|
1259
|
+
* Permanently removes everything in the Trash for a user. Folders are
|
|
1260
|
+
* processed root-first so removing a parent also removes its contents.
|
|
1261
|
+
*/
|
|
1262
|
+
empty(userId: string): Promise<EmptyTrashResult>;
|
|
1263
|
+
/** Restores a single trashed item (used by the batch restore endpoint). */
|
|
1264
|
+
verifyTrashedFile(userId: string, id: string): Promise<FileRecord>;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
interface IntegrityCheckOptions {
|
|
1268
|
+
/** Re-download and re-hash objects (slow but authoritative). */
|
|
1269
|
+
deep?: boolean;
|
|
1270
|
+
/** Maximum files to inspect in one pass. */
|
|
1271
|
+
limit?: number;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Detects drift between PostgreSQL metadata and Telegram storage:
|
|
1275
|
+
*
|
|
1276
|
+
* - `missing` — metadata exists, the Telegram message is gone
|
|
1277
|
+
* - `size_mismatch` — the stored object's size differs from the metadata
|
|
1278
|
+
* - `hash_mismatch` — deep mode only: downloaded bytes don't match sha256
|
|
1279
|
+
* - `unreadable` — the provider errored while inspecting the object
|
|
1280
|
+
*
|
|
1281
|
+
* The checker is strictly read-only: repairs are a separate, explicit step so
|
|
1282
|
+
* nothing is ever deleted silently (see the v0.2 reliability rules).
|
|
1283
|
+
*/
|
|
1284
|
+
declare class IntegrityService {
|
|
1285
|
+
private readonly files;
|
|
1286
|
+
private readonly engineFor;
|
|
1287
|
+
constructor(files: FileRepository, engineFor: EngineResolver);
|
|
1288
|
+
check(userId: string, options?: IntegrityCheckOptions): Promise<IntegrityReportDTO>;
|
|
1289
|
+
private inspect;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* Recent view: the most recently touched active files, newest activity first.
|
|
1294
|
+
* Trashed and permanently-deleted files are filtered out so the view never
|
|
1295
|
+
* surfaces items the user cannot open.
|
|
1296
|
+
*/
|
|
1297
|
+
declare class RecentService {
|
|
1298
|
+
private readonly activity;
|
|
1299
|
+
private readonly files;
|
|
1300
|
+
constructor(activity: ActivityRepository, files: FileRepository);
|
|
1301
|
+
list(userId: string, page: PageRequest): Promise<RecentPageDTO>;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Sanitizes a client-supplied filename into a safe, single path component.
|
|
1306
|
+
* Returns an empty string when nothing usable remains.
|
|
1307
|
+
*/
|
|
1308
|
+
declare function sanitizeFileName(name: string): string;
|
|
1309
|
+
|
|
1310
|
+
interface TelegramCredentials {
|
|
1311
|
+
apiId: number;
|
|
1312
|
+
apiHash: string;
|
|
1313
|
+
}
|
|
1314
|
+
interface ConnectionStatus {
|
|
1315
|
+
state: ConnectionState;
|
|
1316
|
+
lastError: string | null;
|
|
1317
|
+
lastCheckAt: Date | null;
|
|
1318
|
+
healthy: boolean | null;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Owns one Telegram (MTProto) connection per authenticated user and tracks an
|
|
1322
|
+
* explicit lifecycle state for each:
|
|
1323
|
+
*
|
|
1324
|
+
* DISCONNECTED → CONNECTING → CONNECTED
|
|
1325
|
+
* ↘ RECONNECTING → CONNECTED
|
|
1326
|
+
* ↘ ERROR | AUTH_REQUIRED
|
|
1327
|
+
*
|
|
1328
|
+
* Responsibilities: connect, disconnect, reconnect, validateSession,
|
|
1329
|
+
* healthCheck, refreshConnection. Sessions never leave the server.
|
|
1330
|
+
*/
|
|
1331
|
+
declare class TelegramClientManager {
|
|
1332
|
+
private readonly credentials;
|
|
1333
|
+
private readonly sessions;
|
|
1334
|
+
private connections;
|
|
1335
|
+
private lastReconnectAt;
|
|
1336
|
+
constructor(credentials: TelegramCredentials, sessions: SessionRepository);
|
|
1337
|
+
/** Returns a connected client, (re)connecting when needed. */
|
|
1338
|
+
getForUser(userId: string): Promise<TelegramClient>;
|
|
1339
|
+
/** Connection status for health reporting and the storage dashboard. */
|
|
1340
|
+
statusForUser(userId: string): ConnectionStatus;
|
|
1341
|
+
/**
|
|
1342
|
+
* Probes a user's connection. Cheap by default (connection state only);
|
|
1343
|
+
* `deep` performs a real Telegram round-trip to validate the session.
|
|
1344
|
+
*/
|
|
1345
|
+
healthCheck(userId: string, deep?: boolean): Promise<StorageHealth>;
|
|
1346
|
+
/** Registers an already-authenticated client (from the login flow). */
|
|
1347
|
+
cacheClient(userId: string, client: TelegramClient): void;
|
|
1348
|
+
/** Drops a user's connection (e.g. after logout) without touching storage. */
|
|
1349
|
+
disconnectUser(userId: string): Promise<void>;
|
|
1350
|
+
disconnectAll(): Promise<void>;
|
|
1351
|
+
private isConnected;
|
|
1352
|
+
private connectUser;
|
|
1353
|
+
private reconnect;
|
|
1354
|
+
private establish;
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* Maps a Telegram (GramJS) failure to a structured domain error with an
|
|
1359
|
+
* appropriate HTTP status and a client-facing message that never leaks
|
|
1360
|
+
* credentials or session material.
|
|
1361
|
+
*/
|
|
1362
|
+
declare function mapTelegramError(error: unknown, fallbackMessage: string): DomainError;
|
|
1363
|
+
|
|
1364
|
+
interface TelegramStorageOptions {
|
|
1365
|
+
/** Raw channel id of the user's private storage channel. */
|
|
1366
|
+
chatId: string;
|
|
1367
|
+
/** Channel access hash required to build the input peer. */
|
|
1368
|
+
accessHash: string;
|
|
1369
|
+
/** Human-readable channel title, surfaced in health reporting. */
|
|
1370
|
+
title?: string;
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* StorageProvider implementation backed by the user's private Telegram
|
|
1374
|
+
* channel. Files are sent as force-downloaded documents (no compression), so
|
|
1375
|
+
* every upload is a document message in the channel.
|
|
1376
|
+
*
|
|
1377
|
+
* v0.2 adds progress reporting, cancellation, streamed downloads and a
|
|
1378
|
+
* health check, all translated into the provider-agnostic core vocabulary.
|
|
1379
|
+
*/
|
|
1380
|
+
declare class TelegramStorageProvider implements StorageProvider {
|
|
1381
|
+
private readonly client;
|
|
1382
|
+
readonly name = "telegram";
|
|
1383
|
+
private readonly peer;
|
|
1384
|
+
private readonly title;
|
|
1385
|
+
constructor(client: TelegramClient, options: TelegramStorageOptions);
|
|
1386
|
+
put(input: StorageUploadInput, control?: TransferControl): Promise<StoredObject>;
|
|
1387
|
+
get(ref: StoredRef, control?: TransferControl): Promise<Buffer>;
|
|
1388
|
+
getStream(ref: StoredRef, control?: TransferControl): Promise<Readable>;
|
|
1389
|
+
delete(ref: StoredRef): Promise<void>;
|
|
1390
|
+
exists(ref: StoredRef): Promise<boolean>;
|
|
1391
|
+
stat(ref: StoredRef): Promise<StoredObject | null>;
|
|
1392
|
+
/**
|
|
1393
|
+
* Validates that the client is connected and the storage channel is
|
|
1394
|
+
* reachable (a real Telegram round-trip on the channel peer).
|
|
1395
|
+
*/
|
|
1396
|
+
healthCheck(): Promise<StorageHealth>;
|
|
1397
|
+
private throwIfAborted;
|
|
1398
|
+
private materialize;
|
|
1399
|
+
private documentSize;
|
|
1400
|
+
private requireMessage;
|
|
1401
|
+
private getMessage;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
declare const TELEGRAM_PROVIDER = "telegram";
|
|
1405
|
+
type VerifyCodeResult = {
|
|
1406
|
+
status: "ok";
|
|
1407
|
+
user: UserRecord;
|
|
1408
|
+
} | {
|
|
1409
|
+
status: "password_required";
|
|
1410
|
+
};
|
|
1411
|
+
/**
|
|
1412
|
+
* Orchestrates the full Telegram account connection flow:
|
|
1413
|
+
* phone → code (→ 2FA password) → session persisted → user upserted →
|
|
1414
|
+
* private storage channel created.
|
|
1415
|
+
*/
|
|
1416
|
+
declare class TelegramConnectionService {
|
|
1417
|
+
private readonly repos;
|
|
1418
|
+
private readonly clientManager;
|
|
1419
|
+
private readonly credentials;
|
|
1420
|
+
private flows;
|
|
1421
|
+
constructor(repos: Repos, clientManager: TelegramClientManager, credentials: TelegramCredentials);
|
|
1422
|
+
/** Sends the Telegram confirmation code for the phone number. */
|
|
1423
|
+
startLogin(phone: string): Promise<void>;
|
|
1424
|
+
/** Verifies the confirmation code. Returns `password_required` for 2FA accounts. */
|
|
1425
|
+
verifyCode(phone: string, code: string): Promise<VerifyCodeResult>;
|
|
1426
|
+
/** Completes sign-in for accounts with two-factor authentication enabled. */
|
|
1427
|
+
verifyPassword(phone: string, password: string): Promise<VerifyCodeResult>;
|
|
1428
|
+
/** Aborts a pending login flow (disconnects the client). */
|
|
1429
|
+
cancelLogin(phone: string): Promise<void>;
|
|
1430
|
+
/**
|
|
1431
|
+
* Ensures the user has a registered private storage channel, creating it
|
|
1432
|
+
* on first use. Idempotent.
|
|
1433
|
+
*/
|
|
1434
|
+
ensureStorage(userId: string): Promise<StorageRecord>;
|
|
1435
|
+
ensureStorageForClient(userId: string, client: TelegramClient): Promise<StorageRecord>;
|
|
1436
|
+
private requireFlow;
|
|
1437
|
+
private finalizeLogin;
|
|
1438
|
+
private sweepExpiredFlows;
|
|
1439
|
+
private disconnectQuietly;
|
|
1440
|
+
}
|
|
447
1441
|
|
|
448
|
-
export { type ActivityEventDTO, type ActivityPageDTO, type ApiErrorBody, type BatchResultDTO, type ConnectionState, type DownloadProgress, type DownloadResult, ERROR_CODES, type EmptyTrashResultDTO, type ErrorCode, type FileDTO, type FileVersionDTO, type FilesPageDTO, type FolderDTO, type FolderMutationResultDTO, type FoldersPageDTO, type HealthDTO, type HealthStatus, type IntegrityIssueDTO, type IntegrityReportDTO, OmniCloudClient, type OmniCloudClientOptions, OmniCloudError, type PaginationDTO, type RecentItemDTO, type RecentPageDTO, type RetryOptions, type SearchResultDTO, type SessionInfo, type StorageDTO, type StorageHealthDTO, type StorageStatsDTO, type StorageTypeBreakdownDTO, type TelegramVerifyResponse, type TrashPageDTO, type UploadInput, type UploadOptions, type UploadProgress, type UserDTO };
|
|
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 };
|