@brftech/filex-core 0.19.0 → 0.20.0
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/README.md +34 -4
- package/dist/filex-core.js +10626 -6501
- package/dist/filex-core.js.map +1 -1
- package/dist/filex-core.umd.cjs +94 -63
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/index.d.ts +1026 -7
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/FileExplorer.vue +103 -68
- package/src/components/ConnectionGuideView.vue +333 -0
- package/src/components/ConnectionsPanel.vue +912 -0
- package/src/components/NFSExportsPanel.vue +283 -0
- package/src/components/S3KeysPanel.vue +381 -0
- package/src/components/SSHKeysPanel.vue +222 -0
- package/src/components/StorageFields.vue +362 -0
- package/src/components/TokensPanel.vue +191 -0
- package/src/components/UploadProgress.vue +5 -1
- package/src/composables/useConnections.ts +271 -0
- package/src/composables/useFileApi.ts +15 -2
- package/src/composables/useNFSExports.ts +148 -0
- package/src/composables/useS3Keys.ts +175 -0
- package/src/composables/useSSHKeys.ts +119 -0
- package/src/composables/useThumbs.ts +1 -1
- package/src/composables/useTokens.ts +121 -0
- package/src/composables/useUploadChunked.ts +433 -164
- package/src/index.ts +77 -2
- package/src/lib/connectionGuides.ts +1279 -0
- package/src/lib/realtime.ts +1 -1
- package/src/lib/uploadResume.ts +157 -0
- package/src/locales/en.ts +413 -0
- package/src/locales/tr.ts +416 -0
- package/src/modals/ConvertModal.vue +1 -1
- package/src/styles/base.css +12 -12
- package/src/types/Connections.ts +122 -0
- package/src/types/ExplorerConfig.ts +23 -2
- package/src/types/NFSExports.ts +47 -0
- package/src/types/S3Keys.ts +55 -0
- package/src/types/SSHKeys.ts +54 -0
- package/src/types/Tokens.ts +39 -0
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { GlobalComponents } from 'vue';
|
|
|
7
7
|
import { GlobalDirectives } from 'vue';
|
|
8
8
|
import { PublicProps } from 'vue';
|
|
9
9
|
import { Ref } from 'vue';
|
|
10
|
+
import { ShallowRef } from 'vue';
|
|
10
11
|
|
|
11
12
|
declare type __VLS_Props = {
|
|
12
13
|
config: ExplorerConfig;
|
|
@@ -60,6 +61,65 @@ declare type __VLS_Props_12 = {
|
|
|
60
61
|
busy?: boolean;
|
|
61
62
|
};
|
|
62
63
|
|
|
64
|
+
declare type __VLS_Props_13 = {
|
|
65
|
+
config: ExplorerConfig;
|
|
66
|
+
/** Which half to open on. */
|
|
67
|
+
initialTab?: 'storages' | 'connect';
|
|
68
|
+
/** Draw a close control — the desktop app opens this as a full surface
|
|
69
|
+
* and needs a way out; a page-embedded copy has the page's own chrome. */
|
|
70
|
+
closable?: boolean;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
declare type __VLS_Props_14 = {
|
|
74
|
+
fields: StorageField[];
|
|
75
|
+
modelValue: Record<string, unknown>;
|
|
76
|
+
locale: LocaleCode;
|
|
77
|
+
/** Keys to mark as failing validation (missing required). */
|
|
78
|
+
invalid?: string[];
|
|
79
|
+
disabled?: boolean;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
declare type __VLS_Props_15 = {
|
|
83
|
+
guide: ProtocolGuide;
|
|
84
|
+
locale: LocaleCode;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
declare type __VLS_Props_16 = {
|
|
88
|
+
config: ExplorerConfig;
|
|
89
|
+
/** Storage names the caller may see, for the confinement picker. */
|
|
90
|
+
storages: string[];
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
declare type __VLS_Props_17 = {
|
|
94
|
+
config: ExplorerConfig;
|
|
95
|
+
/**
|
|
96
|
+
* Draw the key list and the paste box.
|
|
97
|
+
*
|
|
98
|
+
* ⚠ False for FTPS, which authenticates with a password or an API token and
|
|
99
|
+
* has no use for an SSH key — the panel is still MOUNTED there because it is
|
|
100
|
+
* the call that reports where the FTP endpoint listens and under what login
|
|
101
|
+
* name. Showing a key box on the FTPS page would invite somebody to register
|
|
102
|
+
* a key that protocol will never look at.
|
|
103
|
+
*/
|
|
104
|
+
keysVisible?: boolean;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
declare type __VLS_Props_18 = {
|
|
108
|
+
config: ExplorerConfig;
|
|
109
|
+
/** Storage names the caller may see, for the confinement picker. */
|
|
110
|
+
storages: string[];
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
declare type __VLS_Props_19 = {
|
|
114
|
+
config: ExplorerConfig;
|
|
115
|
+
/**
|
|
116
|
+
* Which protocol the surrounding guide is showing. It only changes the
|
|
117
|
+
* default label — a token minted here works on all of them, and pretending
|
|
118
|
+
* otherwise would have people mint one per protocol.
|
|
119
|
+
*/
|
|
120
|
+
protocol?: string;
|
|
121
|
+
};
|
|
122
|
+
|
|
63
123
|
declare type __VLS_Props_2 = {
|
|
64
124
|
open: boolean;
|
|
65
125
|
locale: LocaleCode;
|
|
@@ -178,6 +238,45 @@ declare type __VLS_Props_9 = {
|
|
|
178
238
|
narrow?: boolean;
|
|
179
239
|
};
|
|
180
240
|
|
|
241
|
+
/**
|
|
242
|
+
* The self-service API-token surface (`/api/tokens`).
|
|
243
|
+
*
|
|
244
|
+
* ⚠ Why this exists at all: three of the six protocols filex serves take an
|
|
245
|
+
* API token as their password — FTPS, WebDAV and `filex mount`. Until
|
|
246
|
+
* 2026-08-17 the only place to mint one was `/api/admin/ai-tokens`, which is
|
|
247
|
+
* admin-only, so a normal user opened the FTPS guide, read "use an API token
|
|
248
|
+
* as the password", and had nowhere to get one. The backend route has always
|
|
249
|
+
* been open to every account; only the UI was missing.
|
|
250
|
+
*/
|
|
251
|
+
/** One token row. The secret is NEVER in here — only the hash is stored. */
|
|
252
|
+
export declare interface ApiToken {
|
|
253
|
+
id: number;
|
|
254
|
+
label: string;
|
|
255
|
+
scopes: string;
|
|
256
|
+
/** Per-token display identities for the audit trail; may be absent. */
|
|
257
|
+
usernames?: string | null;
|
|
258
|
+
created_at?: string;
|
|
259
|
+
last_used_at?: string | null;
|
|
260
|
+
expires_at?: string | null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** What comes back from a mint. `token` is shown exactly once. */
|
|
264
|
+
export declare interface ApiTokenCreated {
|
|
265
|
+
token: string;
|
|
266
|
+
row: ApiToken;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export declare interface ApiTokenRequest {
|
|
270
|
+
label: string;
|
|
271
|
+
/**
|
|
272
|
+
* Comma-separated verbs. The server CAPS this against the caller's role and
|
|
273
|
+
* their own grants, so asking for more than you have is refused rather than
|
|
274
|
+
* quietly granted — never send `admin`, it is rejected outright here.
|
|
275
|
+
*/
|
|
276
|
+
scopes?: string;
|
|
277
|
+
expires_in_days?: number;
|
|
278
|
+
}
|
|
279
|
+
|
|
181
280
|
/**
|
|
182
281
|
* Set (or clear, for the default theme) the selected theme's tokens as
|
|
183
282
|
* inline CSS variables on the explorer root element, resolved to the
|
|
@@ -245,6 +344,42 @@ export declare type AuthConfig = {
|
|
|
245
344
|
csrf: string;
|
|
246
345
|
};
|
|
247
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Every command here was RUN against the endpoint on 2026-08-16 with curl
|
|
349
|
+
* 8.5, lftp 4.9 and rclone 1.73 — including the settings each of them needs to
|
|
350
|
+
* negotiate explicit TLS, which is the half of FTPS that goes wrong quietly.
|
|
351
|
+
*/
|
|
352
|
+
export declare const buildFtpsGuide: GuideBuilder;
|
|
353
|
+
|
|
354
|
+
export declare function buildGuide(protocol: string, ctx: GuideContext, t: Translate): ProtocolGuide | null;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Every command here was RUN against the endpoint on 2026-08-16 with the LINUX
|
|
358
|
+
* KERNEL's own NFSv3 client — including the two options a mount fails silently
|
|
359
|
+
* without (`port=` and `mountport=`, because filex serves both on one port and
|
|
360
|
+
* runs no portmapper).
|
|
361
|
+
*/
|
|
362
|
+
export declare const buildNfsGuide: GuideBuilder;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Every command here was RUN against the endpoint on 2026-08-16, not copied
|
|
366
|
+
* from a vendor page: rclone 1.73.5, aws-cli 2.11.6, restic 0.19.1, mc
|
|
367
|
+
* 2025-08-13 and s3fs 1.93 each did a full round trip, and the flags below are
|
|
368
|
+
* the ones those runs actually needed. Five of the endpoint's bugs were found
|
|
369
|
+
* that way — a guide assembled from documentation would have shipped them.
|
|
370
|
+
*/
|
|
371
|
+
export declare const buildS3Guide: GuideBuilder;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Every command here was RUN against the endpoint on 2026-08-16 with OpenSSH
|
|
375
|
+
* 9.6 and rclone 1.73 — including the two settings rclone needs because filex
|
|
376
|
+
* has no shell, which are the difference between a clean run and a pile of
|
|
377
|
+
* warnings about a missing `md5sum`.
|
|
378
|
+
*/
|
|
379
|
+
export declare const buildSftpGuide: GuideBuilder;
|
|
380
|
+
|
|
381
|
+
export declare const buildWebdavGuide: GuideBuilder;
|
|
382
|
+
|
|
248
383
|
export declare interface Capabilities {
|
|
249
384
|
ffmpeg?: boolean;
|
|
250
385
|
ghostscript?: boolean;
|
|
@@ -261,6 +396,8 @@ export declare interface Capabilities {
|
|
|
261
396
|
};
|
|
262
397
|
}
|
|
263
398
|
|
|
399
|
+
export declare function clearResume(store: ResumeStorage | null, key: string): void;
|
|
400
|
+
|
|
264
401
|
export declare interface ClipboardState {
|
|
265
402
|
mode: 'cut' | 'copy' | null;
|
|
266
403
|
items: FileNode[];
|
|
@@ -274,6 +411,53 @@ export declare interface ClipboardState {
|
|
|
274
411
|
*/
|
|
275
412
|
export declare function comboFromEvent(e: KeyboardEvent): string | null;
|
|
276
413
|
|
|
414
|
+
export declare const ConnectionGuideView: DefineComponent<__VLS_Props_15, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_15> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
415
|
+
|
|
416
|
+
export declare type ConnectionsApi = ReturnType<typeof useConnections>;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* The URL prefix the `/api/...` routes hang off.
|
|
420
|
+
*
|
|
421
|
+
* `apiBase: ''` is a legitimate value (the admin SPA is same-origin), so
|
|
422
|
+
* only `undefined`/`null` means "not given" — a falsy check would send the
|
|
423
|
+
* SPA's requests to the wrong place. Legacy embedders configure `endpoint`
|
|
424
|
+
* instead of `apiBase`; the prefix is recovered from it so they are not
|
|
425
|
+
* excluded.
|
|
426
|
+
*/
|
|
427
|
+
export declare function connectionsBase(config: ExplorerConfig): string;
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* The origin a client program should be pointed at.
|
|
431
|
+
*
|
|
432
|
+
* The instruction pages are only worth anything if they name the real
|
|
433
|
+
* deployment, so this resolves to an absolute origin: the configured
|
|
434
|
+
* apiBase when there is one (the desktop app, embeds), otherwise the page's
|
|
435
|
+
* own origin (the admin SPA, which is served by the same binary).
|
|
436
|
+
*/
|
|
437
|
+
export declare function connectionsOrigin(config: ExplorerConfig): string;
|
|
438
|
+
|
|
439
|
+
export declare const ConnectionsPanel: DefineComponent<__VLS_Props_13, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
440
|
+
error: (err: {
|
|
441
|
+
message: string;
|
|
442
|
+
}) => any;
|
|
443
|
+
close: () => any;
|
|
444
|
+
changed: () => any;
|
|
445
|
+
}, string, PublicProps, Readonly<__VLS_Props_13> & Readonly<{
|
|
446
|
+
onError?: ((err: {
|
|
447
|
+
message: string;
|
|
448
|
+
}) => any) | undefined;
|
|
449
|
+
onClose?: (() => any) | undefined;
|
|
450
|
+
onChanged?: (() => any) | undefined;
|
|
451
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
452
|
+
|
|
453
|
+
/** The signed-in account, from `GET /api/auth/me`. */
|
|
454
|
+
export declare interface ConnectionsUser {
|
|
455
|
+
id: number;
|
|
456
|
+
email: string;
|
|
457
|
+
display_name?: string;
|
|
458
|
+
role?: string;
|
|
459
|
+
}
|
|
460
|
+
|
|
277
461
|
declare interface ContextAction {
|
|
278
462
|
key: string;
|
|
279
463
|
label: string;
|
|
@@ -312,6 +496,11 @@ export declare function decryptFile(kek: CryptoKey, data: ArrayBuffer): Promise<
|
|
|
312
496
|
|
|
313
497
|
export declare const DEFAULT_THEME_ID = "default";
|
|
314
498
|
|
|
499
|
+
/** The default backing store, or null where the platform has none. Reading
|
|
500
|
+
* localStorage throws in a partitioned/blocked context, so the probe is a real
|
|
501
|
+
* try, not a typeof check. */
|
|
502
|
+
export declare function defaultResumeStorage(): ResumeStorage | null;
|
|
503
|
+
|
|
315
504
|
declare type Density = 'comfortable' | 'compact';
|
|
316
505
|
|
|
317
506
|
/**
|
|
@@ -406,6 +595,15 @@ export declare function encryptFile(kek: CryptoKey, content: ArrayBuffer): Promi
|
|
|
406
595
|
*/
|
|
407
596
|
export declare interface EndpointMap {
|
|
408
597
|
manager: string;
|
|
598
|
+
/**
|
|
599
|
+
* Staged upload — the chunked, resumable, driver-agnostic path every client
|
|
600
|
+
* speaks (docs/UPLOADS.md). The per-upload routes (`PUT/GET/DELETE {id}`,
|
|
601
|
+
* `POST {id}/commit`) are derived from it by stripping `/begin`, so one
|
|
602
|
+
* override moves the whole protocol.
|
|
603
|
+
*/
|
|
604
|
+
uploadBegin: string | null;
|
|
605
|
+
/** Legacy S3-presigned chunked upload. Still served by the backend for
|
|
606
|
+
* older embedders; nothing in this package calls it. */
|
|
409
607
|
uploadInit: string | null;
|
|
410
608
|
uploadFinalize: string | null;
|
|
411
609
|
uploadAbort: string | null;
|
|
@@ -448,6 +646,8 @@ export declare interface ExplorerConfig {
|
|
|
448
646
|
apiBase?: string;
|
|
449
647
|
/** Legacy main endpoint (Vuefinder-compat: GET/POST `?q=…`). */
|
|
450
648
|
endpoint?: string;
|
|
649
|
+
/** Staged upload entry point; the `{id}` routes hang off it. */
|
|
650
|
+
uploadBegin?: string;
|
|
451
651
|
uploadInit?: string;
|
|
452
652
|
uploadFinalize?: string;
|
|
453
653
|
uploadAbort?: string;
|
|
@@ -538,9 +738,19 @@ export declare interface ExplorerConfig {
|
|
|
538
738
|
* embed). Defaults to `/files/viewer`.
|
|
539
739
|
*/
|
|
540
740
|
viewerBaseUrl?: string;
|
|
541
|
-
/**
|
|
741
|
+
/**
|
|
742
|
+
* Upload chunk size (bytes). Default 8 MB — the server's default too, so
|
|
743
|
+
* "large enough to chunk" means the same thing on both ends. The value the
|
|
744
|
+
* server returns from `begin` is binding; this is what the client asks for
|
|
745
|
+
* and the threshold above which a file goes on the staged path at all.
|
|
746
|
+
*/
|
|
542
747
|
chunkSize?: number;
|
|
543
|
-
/**
|
|
748
|
+
/**
|
|
749
|
+
* @deprecated Ignored since the move to the staged protocol. Chunks are sent
|
|
750
|
+
* sequentially because `offset` — the resume point — is the contiguous run
|
|
751
|
+
* from part 1; parallel parts would leave holes that a resumed upload has to
|
|
752
|
+
* re-send anyway.
|
|
753
|
+
*/
|
|
544
754
|
parallelChunks?: number;
|
|
545
755
|
/** Theme. */
|
|
546
756
|
theme?: ThemeMode;
|
|
@@ -1064,6 +1274,22 @@ export declare interface FileNode {
|
|
|
1064
1274
|
*/
|
|
1065
1275
|
export declare function findShortcutConflict(combo: string, excludeId: string): ShortcutConflict | null;
|
|
1066
1276
|
|
|
1277
|
+
/** What an FTP client needs to be told, computed on the server. */
|
|
1278
|
+
declare interface FTPSFacts {
|
|
1279
|
+
enabled: boolean;
|
|
1280
|
+
host: string;
|
|
1281
|
+
port: number;
|
|
1282
|
+
/**
|
|
1283
|
+
* ⚠ The passive data-port range. A firewall that blocks it makes every
|
|
1284
|
+
* transfer HANG with no error on either side — the classic FTP failure, and
|
|
1285
|
+
* impossible to diagnose from the client end. It belongs in the guide.
|
|
1286
|
+
*/
|
|
1287
|
+
pasv_min: number;
|
|
1288
|
+
pasv_max: number;
|
|
1289
|
+
/** True when no certificate was configured and the server generated one. */
|
|
1290
|
+
self_signed: boolean;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1067
1293
|
/**
|
|
1068
1294
|
* Generate a stylesheet that mirrors styles/variables.css' selector
|
|
1069
1295
|
* cascade 1:1 (light base → explicit-dark selectors → prefers-dark media
|
|
@@ -1120,9 +1346,112 @@ declare interface Grant {
|
|
|
1120
1346
|
inherited?: boolean;
|
|
1121
1347
|
}
|
|
1122
1348
|
|
|
1349
|
+
/**
|
|
1350
|
+
* Protocol id → builder.
|
|
1351
|
+
*
|
|
1352
|
+
* S3 and SFTP land here as one entry each once their servers exist; the
|
|
1353
|
+
* panel, the copy buttons, the client tabs and the i18n plumbing are
|
|
1354
|
+
* already written for them. That is the whole point of the shape.
|
|
1355
|
+
*/
|
|
1356
|
+
export declare const GUIDE_BUILDERS: Record<string, GuideBuilder>;
|
|
1357
|
+
|
|
1358
|
+
export declare interface GuideBlock {
|
|
1359
|
+
kind: GuideBlockKind;
|
|
1360
|
+
/** Prose for `text` / `note` / `warn`. */
|
|
1361
|
+
text?: string;
|
|
1362
|
+
/** Ordered instructions for `steps`. */
|
|
1363
|
+
steps?: string[];
|
|
1364
|
+
/** Copyable payload for `code`. */
|
|
1365
|
+
code?: string;
|
|
1366
|
+
/** Syntax hint / file name shown above a code block. */
|
|
1367
|
+
caption?: string;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
export declare type GuideBlockKind = 'text' | 'steps' | 'code' | 'note' | 'warn';
|
|
1371
|
+
|
|
1372
|
+
export declare type GuideBuilder = (ctx: GuideContext, t: Translate) => ProtocolGuide;
|
|
1373
|
+
|
|
1374
|
+
export declare interface GuideClient {
|
|
1375
|
+
id: string;
|
|
1376
|
+
/** Product name — never translated ("Cyberduck" is Cyberduck). */
|
|
1377
|
+
name: string;
|
|
1378
|
+
platform: 'windows' | 'macos' | 'linux' | 'any';
|
|
1379
|
+
blocks: GuideBlock[];
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/** Everything a guide is allowed to know about the deployment. */
|
|
1383
|
+
export declare interface GuideContext {
|
|
1384
|
+
/** Absolute origin of the server, e.g. `https://fm.example.com`. */
|
|
1385
|
+
origin: string;
|
|
1386
|
+
/** The caller's own account e-mail — the username on every protocol. */
|
|
1387
|
+
user: string;
|
|
1388
|
+
/** Storage names the caller may see. */
|
|
1389
|
+
storages: string[];
|
|
1390
|
+
/** The storage the page is currently focused on, when any. */
|
|
1391
|
+
storage?: string;
|
|
1392
|
+
/**
|
|
1393
|
+
* The S3 endpoint, as the server computes it.
|
|
1394
|
+
*
|
|
1395
|
+
* ⚠ NOT derived from `origin` here. With a dedicated host the endpoint is
|
|
1396
|
+
* that host's root; without one it lives under `/s3`, and a client pointed
|
|
1397
|
+
* at the application root reaches the web app — rclone reported
|
|
1398
|
+
* "XML syntax error on line 10" against an HTML redirect page. The server
|
|
1399
|
+
* returns this with every key, and the guide repeats it verbatim.
|
|
1400
|
+
*/
|
|
1401
|
+
s3Endpoint?: string;
|
|
1402
|
+
/** True when clients must be told to force path-style addressing. */
|
|
1403
|
+
s3PathStyle?: boolean;
|
|
1404
|
+
/** The access key id to write into the examples, when the caller has one. */
|
|
1405
|
+
s3AccessKeyID?: string;
|
|
1406
|
+
/** The freshly minted secret, shown only while the user is looking at it. */
|
|
1407
|
+
s3Secret?: string;
|
|
1408
|
+
/** The SFTP endpoint, as the server reports it. */
|
|
1409
|
+
sftpHost?: string;
|
|
1410
|
+
sftpPort?: number;
|
|
1411
|
+
/** False when the operator has the endpoint switched off. */
|
|
1412
|
+
sftpEnabled?: boolean;
|
|
1413
|
+
/** The login name a client must use — the username when there is one. */
|
|
1414
|
+
sftpLogin?: string;
|
|
1415
|
+
/** True when the account has at least one usable key registered. */
|
|
1416
|
+
sftpHasKey?: boolean;
|
|
1417
|
+
/** The FTPS endpoint, as the server reports it. */
|
|
1418
|
+
ftpsHost?: string;
|
|
1419
|
+
ftpsPort?: number;
|
|
1420
|
+
ftpsEnabled?: boolean;
|
|
1421
|
+
/** The passive data-port range, which the client's firewall must allow. */
|
|
1422
|
+
ftpsPasvMin?: number;
|
|
1423
|
+
ftpsPasvMax?: number;
|
|
1424
|
+
/** True when the server is using a self-signed certificate. */
|
|
1425
|
+
ftpsSelfSigned?: boolean;
|
|
1426
|
+
/** The NFS endpoint, as the server reports it. */
|
|
1427
|
+
nfsHost?: string;
|
|
1428
|
+
nfsPort?: number;
|
|
1429
|
+
nfsEnabled?: boolean;
|
|
1430
|
+
/** The freshly minted export path — the credential, shown once. */
|
|
1431
|
+
nfsPath?: string;
|
|
1432
|
+
/** True when the active export refuses writes. */
|
|
1433
|
+
nfsReadOnly?: boolean;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
/** One connection fact, rendered as a copyable row. */
|
|
1437
|
+
export declare interface GuideFact {
|
|
1438
|
+
label: string;
|
|
1439
|
+
value: string;
|
|
1440
|
+
hint?: string;
|
|
1441
|
+
/** Rendered as a hint rather than a value — filex never has the
|
|
1442
|
+
* plaintext of your password and must not pretend otherwise. */
|
|
1443
|
+
placeholderOnly?: boolean;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
/** Protocol ids that have a guide, in display order. */
|
|
1447
|
+
export declare function guideProtocols(): string[];
|
|
1448
|
+
|
|
1123
1449
|
/** True when the buffer starts with the 'filexe2e' magic. */
|
|
1124
1450
|
export declare function hasMagic(buf: ArrayBuffer | Uint8Array): boolean;
|
|
1125
1451
|
|
|
1452
|
+
/** `https://fm.example.com` → `fm.example.com`; anything unparseable comes back whole. */
|
|
1453
|
+
export declare function hostOf(origin: string): string;
|
|
1454
|
+
|
|
1126
1455
|
declare interface InviteResponse {
|
|
1127
1456
|
mode: 'granted' | 'user_created' | 'shared';
|
|
1128
1457
|
user_id?: number;
|
|
@@ -1138,8 +1467,31 @@ declare interface InviteResponse {
|
|
|
1138
1467
|
*/
|
|
1139
1468
|
export declare function isExternalUsable(s: ExternalServiceStatus | undefined): boolean;
|
|
1140
1469
|
|
|
1470
|
+
/** True when the deployment is not on TLS — several clients refuse that,
|
|
1471
|
+
* and Windows refuses it silently, which is worse. */
|
|
1472
|
+
export declare function isPlainHttp(origin: string): boolean;
|
|
1473
|
+
|
|
1474
|
+
/** True when the staged protocol is simply not there. */
|
|
1475
|
+
export declare function isStagedUnsupported(err: unknown): boolean;
|
|
1476
|
+
|
|
1477
|
+
/** Every unfinished upload this browser knows about, newest first. Surfaces
|
|
1478
|
+
* use it to say "you have an unfinished upload" instead of forgetting. */
|
|
1479
|
+
export declare function listResume(store: ResumeStorage | null, now?: number): ResumeRecord[];
|
|
1480
|
+
|
|
1481
|
+
/** The record for this exact (destination, file), or null. */
|
|
1482
|
+
export declare function loadResume(store: ResumeStorage | null, key: string, now?: number): ResumeRecord | null;
|
|
1483
|
+
|
|
1141
1484
|
export declare type LocaleCode = 'tr' | 'en';
|
|
1142
1485
|
|
|
1486
|
+
/**
|
|
1487
|
+
* Why the caller cannot manage storages, when they cannot.
|
|
1488
|
+
*
|
|
1489
|
+
* `none` is the honest answer for a signed-in non-admin: the surface then
|
|
1490
|
+
* shows the connection guides (which every user needs) and a plain "ask
|
|
1491
|
+
* your administrator" line instead of a form that would 403 on submit.
|
|
1492
|
+
*/
|
|
1493
|
+
export declare type ManageDenial = 'none' | 'anonymous' | 'unreachable';
|
|
1494
|
+
|
|
1143
1495
|
export declare interface ManagerResponse {
|
|
1144
1496
|
adapter: string;
|
|
1145
1497
|
storages: string[];
|
|
@@ -1158,6 +1510,71 @@ export declare function matchedInContent(matched: unknown): boolean;
|
|
|
1158
1510
|
|
|
1159
1511
|
export declare const messages: Record<LocaleCode, Record<string, string>>;
|
|
1160
1512
|
|
|
1513
|
+
/** Where an NFS client should point, reported by the server. */
|
|
1514
|
+
export declare interface NFSConnection {
|
|
1515
|
+
/** The FILEX_NFS kill switch. */
|
|
1516
|
+
enabled: boolean;
|
|
1517
|
+
host: string;
|
|
1518
|
+
/**
|
|
1519
|
+
* ⚠ 2049 by convention, but filex serves mount AND nfs on this one port and
|
|
1520
|
+
* runs no portmapper — so a client needs `port=` and `mountport=` both set to
|
|
1521
|
+
* it. A guide that omitted either produces a mount that hangs.
|
|
1522
|
+
*/
|
|
1523
|
+
port: number;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
/**
|
|
1527
|
+
* NFS exports, as the frontend sees them.
|
|
1528
|
+
*
|
|
1529
|
+
* ⚠⚠ The `path` a freshly minted export returns IS the credential. NFSv3 cannot
|
|
1530
|
+
* authenticate a request without Kerberos, so filex binds the identity to the
|
|
1531
|
+
* export path instead: 32 bytes of entropy, shown once, stored hashed. Whoever
|
|
1532
|
+
* knows it can mount as that account — which is why it belongs in a config file
|
|
1533
|
+
* treated like a password, and why the UI has to say so rather than letting
|
|
1534
|
+
* somebody discover it from a mount table.
|
|
1535
|
+
*/
|
|
1536
|
+
export declare interface NFSExport {
|
|
1537
|
+
id: number;
|
|
1538
|
+
user_id: number;
|
|
1539
|
+
api_token_id?: number | null;
|
|
1540
|
+
label: string;
|
|
1541
|
+
/** Confinement, in the same shape the S3 keys use. */
|
|
1542
|
+
storage_name?: string;
|
|
1543
|
+
prefix?: string;
|
|
1544
|
+
/** Refuses every write through this mount, whatever the account may do. */
|
|
1545
|
+
read_only: boolean;
|
|
1546
|
+
/** Comma-separated CIDR allow-list. Empty = any address the listener takes. */
|
|
1547
|
+
allow_cidrs?: string;
|
|
1548
|
+
created_at: string;
|
|
1549
|
+
last_used_at?: string | null;
|
|
1550
|
+
expires_at?: string | null;
|
|
1551
|
+
disabled_at?: string | null;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
/** What minting returns. The path appears exactly once. */
|
|
1555
|
+
export declare interface NFSExportCreated extends NFSConnection {
|
|
1556
|
+
export: NFSExport;
|
|
1557
|
+
path: string;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
export declare const NFSExportsPanel: DefineComponent<__VLS_Props_18, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
1561
|
+
active: (v: {
|
|
1562
|
+
host: string;
|
|
1563
|
+
port: number;
|
|
1564
|
+
enabled: boolean;
|
|
1565
|
+
path?: string;
|
|
1566
|
+
readOnly: boolean;
|
|
1567
|
+
}) => any;
|
|
1568
|
+
}, string, PublicProps, Readonly<__VLS_Props_18> & Readonly<{
|
|
1569
|
+
onActive?: ((v: {
|
|
1570
|
+
host: string;
|
|
1571
|
+
port: number;
|
|
1572
|
+
enabled: boolean;
|
|
1573
|
+
path?: string;
|
|
1574
|
+
readOnly: boolean;
|
|
1575
|
+
}) => any) | undefined;
|
|
1576
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
|
|
1577
|
+
|
|
1161
1578
|
/** Mirrors backend `model.NodeComment` (GET /api/files/comments?node_id=…). */
|
|
1162
1579
|
declare interface NodeComment {
|
|
1163
1580
|
id: number;
|
|
@@ -1350,6 +1767,20 @@ monacoEl: HTMLDivElement;
|
|
|
1350
1767
|
officeEl: HTMLDivElement;
|
|
1351
1768
|
}, any>;
|
|
1352
1769
|
|
|
1770
|
+
export declare interface ProtocolGuide {
|
|
1771
|
+
id: string;
|
|
1772
|
+
/** Protocol name — a wire protocol is not translated either. */
|
|
1773
|
+
name: string;
|
|
1774
|
+
summary: string;
|
|
1775
|
+
/** Server + credential, filled in from this deployment. */
|
|
1776
|
+
facts: GuideFact[];
|
|
1777
|
+
clients: GuideClient[];
|
|
1778
|
+
notes: GuideBlock[];
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
/** Drop records older than RESUME_TTL_MS. Returns what survived. */
|
|
1782
|
+
export declare function pruneResume(store: ResumeStorage | null, now?: number): Store;
|
|
1783
|
+
|
|
1353
1784
|
export declare const QuickLook: DefineComponent<__VLS_Props_8, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
1354
1785
|
close: () => any;
|
|
1355
1786
|
nav: (delta: number) => any;
|
|
@@ -1401,6 +1832,106 @@ declare interface ResolveEmailResponse {
|
|
|
1401
1832
|
*/
|
|
1402
1833
|
export declare function resolveEndpoints(config: ExplorerConfig): EndpointMap;
|
|
1403
1834
|
|
|
1835
|
+
/** How long an unfinished record is worth keeping. The server sweeps its own
|
|
1836
|
+
* staging after FILEX_UPLOAD_STAGING_TTL (24 h by default); a note that
|
|
1837
|
+
* outlives the bytes it describes only produces a confusing "resuming…" that
|
|
1838
|
+
* immediately restarts. */
|
|
1839
|
+
export declare const RESUME_TTL_MS: number;
|
|
1840
|
+
|
|
1841
|
+
export declare interface ResumeRecord {
|
|
1842
|
+
/** Server-side staged upload id. */
|
|
1843
|
+
uploadId: string;
|
|
1844
|
+
/** Destination directory, qualified (`adapter://sub/dir`). */
|
|
1845
|
+
path: string;
|
|
1846
|
+
name: string;
|
|
1847
|
+
size: number;
|
|
1848
|
+
/** File.lastModified — part of the identity, not metadata. */
|
|
1849
|
+
lastModified: number;
|
|
1850
|
+
chunkSize: number;
|
|
1851
|
+
/** Last offset the server acknowledged. Display + triage only. */
|
|
1852
|
+
offset: number;
|
|
1853
|
+
updatedAt: number;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/** A Storage-shaped thing. Injected so tests (and any surface without
|
|
1857
|
+
* localStorage — SSR, a locked-down embed) do not have to fake globals. */
|
|
1858
|
+
export declare interface ResumeStorage {
|
|
1859
|
+
getItem(key: string): string | null;
|
|
1860
|
+
setItem(key: string, value: string): void;
|
|
1861
|
+
removeItem(key: string): void;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* The S3 access-key surface, as the frontend sees it.
|
|
1866
|
+
*
|
|
1867
|
+
* Mirrors `model.S3AccessKey` and the connection facts the key endpoints
|
|
1868
|
+
* return alongside it. The facts travel WITH the keys on purpose: a key
|
|
1869
|
+
* without an endpoint is not a usable credential, and a UI that assembled
|
|
1870
|
+
* the URL itself would be a second place to get it wrong (the application
|
|
1871
|
+
* URL and the S3 endpoint are different hosts whenever one is configured).
|
|
1872
|
+
*/
|
|
1873
|
+
export declare interface S3AccessKey {
|
|
1874
|
+
id: number;
|
|
1875
|
+
access_key_id: string;
|
|
1876
|
+
user_id: number;
|
|
1877
|
+
api_token_id?: number | null;
|
|
1878
|
+
label: string;
|
|
1879
|
+
/** Optional confinement, in the shape S3 clients already understand. */
|
|
1880
|
+
bucket?: string;
|
|
1881
|
+
prefix?: string;
|
|
1882
|
+
created_at: string;
|
|
1883
|
+
last_used_at?: string | null;
|
|
1884
|
+
expires_at?: string | null;
|
|
1885
|
+
/** Set = the key is switched off but still in the audit trail. */
|
|
1886
|
+
disabled_at?: string | null;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/** Where to point a client, and how to address it. */
|
|
1890
|
+
export declare interface S3Connection {
|
|
1891
|
+
/** Absolute endpoint URL — the S3 host's root, or `<app>/s3`. */
|
|
1892
|
+
endpoint: string;
|
|
1893
|
+
/** The FILEX_S3 kill switch. False = the operator turned the endpoint off. */
|
|
1894
|
+
enabled: boolean;
|
|
1895
|
+
/**
|
|
1896
|
+
* True when there is no dedicated host, so clients must be told to force
|
|
1897
|
+
* path-style addressing. A current SDK defaults to virtual-hosted and then
|
|
1898
|
+
* fails at DNS with an error that names neither filex nor the cause.
|
|
1899
|
+
*/
|
|
1900
|
+
path_style: boolean;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/** What a freshly minted key returns. The secret appears exactly once. */
|
|
1904
|
+
export declare interface S3KeyCreated extends S3Connection {
|
|
1905
|
+
key: S3AccessKey;
|
|
1906
|
+
secret: string;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
/** What the caller asked for when minting. */
|
|
1910
|
+
export declare interface S3KeyRequest {
|
|
1911
|
+
label: string;
|
|
1912
|
+
/** Mint FROM an API token, inheriting its scopes, confinement and expiry. */
|
|
1913
|
+
api_token_id?: number;
|
|
1914
|
+
bucket?: string;
|
|
1915
|
+
prefix?: string;
|
|
1916
|
+
expires_at?: string;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
export declare const S3KeysPanel: DefineComponent<__VLS_Props_16, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
1920
|
+
active: (v: {
|
|
1921
|
+
accessKeyID: string;
|
|
1922
|
+
secret?: string;
|
|
1923
|
+
endpoint: string;
|
|
1924
|
+
pathStyle: boolean;
|
|
1925
|
+
}) => any;
|
|
1926
|
+
}, string, PublicProps, Readonly<__VLS_Props_16> & Readonly<{
|
|
1927
|
+
onActive?: ((v: {
|
|
1928
|
+
accessKeyID: string;
|
|
1929
|
+
secret?: string;
|
|
1930
|
+
endpoint: string;
|
|
1931
|
+
pathStyle: boolean;
|
|
1932
|
+
}) => any) | undefined;
|
|
1933
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
|
|
1934
|
+
|
|
1404
1935
|
/** Matched-in values the search contract allows on a hit. */
|
|
1405
1936
|
export declare type SearchMatched = 'name' | 'content' | 'both';
|
|
1406
1937
|
|
|
@@ -1555,6 +2086,64 @@ export declare interface SnippetSegment {
|
|
|
1555
2086
|
*/
|
|
1556
2087
|
export declare function snippetSegments(snippet: string): SnippetSegment[];
|
|
1557
2088
|
|
|
2089
|
+
/** Where an SSH client should connect, and as whom. */
|
|
2090
|
+
export declare interface SSHConnection {
|
|
2091
|
+
/** The FILEX_SFTP kill switch. False = the operator turned the port off. */
|
|
2092
|
+
enabled: boolean;
|
|
2093
|
+
host: string;
|
|
2094
|
+
/**
|
|
2095
|
+
* ⚠ Not 22 and not the web port. SFTP is raw TCP on a port of its own, and
|
|
2096
|
+
* a guide that printed 443 would send every client at a proxy that speaks
|
|
2097
|
+
* only HTTP.
|
|
2098
|
+
*/
|
|
2099
|
+
port: number;
|
|
2100
|
+
/** The login name: the account's username, or its e-mail when it has none. */
|
|
2101
|
+
login: string;
|
|
2102
|
+
/** The FTPS endpoint, reported by the same call. */
|
|
2103
|
+
ftps?: FTPSFacts;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
export declare const SSHKeysPanel: DefineComponent<__VLS_Props_17, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
2107
|
+
active: (v: {
|
|
2108
|
+
host: string;
|
|
2109
|
+
port: number;
|
|
2110
|
+
login: string;
|
|
2111
|
+
enabled: boolean;
|
|
2112
|
+
hasKey: boolean;
|
|
2113
|
+
ftps?: FTPSFacts;
|
|
2114
|
+
}) => any;
|
|
2115
|
+
}, string, PublicProps, Readonly<__VLS_Props_17> & Readonly<{
|
|
2116
|
+
onActive?: ((v: {
|
|
2117
|
+
host: string;
|
|
2118
|
+
port: number;
|
|
2119
|
+
login: string;
|
|
2120
|
+
enabled: boolean;
|
|
2121
|
+
hasKey: boolean;
|
|
2122
|
+
ftps?: FTPSFacts;
|
|
2123
|
+
}) => any) | undefined;
|
|
2124
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
|
|
2125
|
+
|
|
2126
|
+
/**
|
|
2127
|
+
* The SSH key surface, as the frontend sees it.
|
|
2128
|
+
*
|
|
2129
|
+
* Mirrors `model.SSHPublicKey` plus the connection facts the endpoint returns
|
|
2130
|
+
* with it — the host, the port and the LOGIN NAME, which is the piece people
|
|
2131
|
+
* most often get wrong when they type it themselves.
|
|
2132
|
+
*/
|
|
2133
|
+
export declare interface SSHPublicKey {
|
|
2134
|
+
id: number;
|
|
2135
|
+
user_id: number;
|
|
2136
|
+
name: string;
|
|
2137
|
+
/** SHA256 fingerprint, base64, without the `SHA256:` prefix. */
|
|
2138
|
+
fingerprint: string;
|
|
2139
|
+
/** The normalised wire form, `<type> <base64>`. */
|
|
2140
|
+
public_key: string;
|
|
2141
|
+
created_at: string;
|
|
2142
|
+
last_used_at?: string | null;
|
|
2143
|
+
/** Set = the key is switched off but still listed. */
|
|
2144
|
+
disabled_at?: string | null;
|
|
2145
|
+
}
|
|
2146
|
+
|
|
1558
2147
|
export declare const StarButton: DefineComponent<__VLS_Props_3, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
1559
2148
|
error: (message: string) => any;
|
|
1560
2149
|
change: (value: boolean) => any;
|
|
@@ -1563,6 +2152,122 @@ onError?: ((message: string) => any) | undefined;
|
|
|
1563
2152
|
onChange?: ((value: boolean) => any) | undefined;
|
|
1564
2153
|
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLButtonElement>;
|
|
1565
2154
|
|
|
2155
|
+
export declare interface StorageDriverCapabilities {
|
|
2156
|
+
read?: boolean;
|
|
2157
|
+
write?: boolean;
|
|
2158
|
+
move?: boolean;
|
|
2159
|
+
copy?: boolean;
|
|
2160
|
+
delete?: boolean;
|
|
2161
|
+
mkdir?: boolean;
|
|
2162
|
+
presign?: boolean;
|
|
2163
|
+
watch?: boolean;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
export declare interface StorageDriverDescriptor {
|
|
2167
|
+
driver: string;
|
|
2168
|
+
label: string;
|
|
2169
|
+
i18n_key: string;
|
|
2170
|
+
fields: StorageField[];
|
|
2171
|
+
capabilities: StorageDriverCapabilities;
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
/** One config key of a storage driver, as declared by the driver itself. */
|
|
2175
|
+
export declare interface StorageField {
|
|
2176
|
+
key: string;
|
|
2177
|
+
type: StorageFieldType;
|
|
2178
|
+
/** English fallback label — used only when `i18n_key` is missing from
|
|
2179
|
+
* the catalogue, so a driver released after this build still renders
|
|
2180
|
+
* readable labels instead of raw keys. */
|
|
2181
|
+
label: string;
|
|
2182
|
+
help?: string;
|
|
2183
|
+
i18n_key: string;
|
|
2184
|
+
help_i18n_key?: string;
|
|
2185
|
+
required: boolean;
|
|
2186
|
+
/** Credential material: render masked, never log, never put in a URL. */
|
|
2187
|
+
secret: boolean;
|
|
2188
|
+
default?: unknown;
|
|
2189
|
+
placeholder?: string;
|
|
2190
|
+
options?: StorageFieldOption[];
|
|
2191
|
+
min?: number;
|
|
2192
|
+
max?: number;
|
|
2193
|
+
monospace?: boolean;
|
|
2194
|
+
multiline?: boolean;
|
|
2195
|
+
advanced?: boolean;
|
|
2196
|
+
/** THE field that scopes the storage inside the backend (s3 prefix,
|
|
2197
|
+
* local path, sftp/ftp/webdav root). The backend rejects an empty or
|
|
2198
|
+
* "/" value with ROOT_PATH_FORBIDDEN. */
|
|
2199
|
+
root?: boolean;
|
|
2200
|
+
/** Legacy spellings the driver still reads for this field. */
|
|
2201
|
+
aliases?: string[];
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
export declare interface StorageFieldOption {
|
|
2205
|
+
value: string;
|
|
2206
|
+
/** English fallback; `i18n_key` wins when the catalogue has it. */
|
|
2207
|
+
label: string;
|
|
2208
|
+
i18n_key?: string;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
export declare const StorageFields: DefineComponent<__VLS_Props_14, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
2212
|
+
"update:modelValue": (v: Record<string, unknown>) => any;
|
|
2213
|
+
}, string, PublicProps, Readonly<__VLS_Props_14> & Readonly<{
|
|
2214
|
+
"onUpdate:modelValue"?: ((v: Record<string, unknown>) => any) | undefined;
|
|
2215
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
2216
|
+
|
|
2217
|
+
/**
|
|
2218
|
+
* Connections — the shapes the storage-connection surface works with.
|
|
2219
|
+
*
|
|
2220
|
+
* Every one of these mirrors something the BACKEND declares, on purpose.
|
|
2221
|
+
* `StorageField` / `StorageDriverDescriptor` are the wire form of
|
|
2222
|
+
* `backend/internal/storage/descriptor.go`, served by
|
|
2223
|
+
* `GET /api/admin/storage-drivers`: a driver states its own config keys,
|
|
2224
|
+
* their types, which one is the storage root and which hold credentials,
|
|
2225
|
+
* and every surface renders that one declaration.
|
|
2226
|
+
*
|
|
2227
|
+
* The alternative — a form per surface — is exactly what shipped broken:
|
|
2228
|
+
* three of the four drivers the admin UI offered could not be created
|
|
2229
|
+
* through it because the form collected keys the backend never read. A
|
|
2230
|
+
* second hand-written form in the desktop app would have been a fourth
|
|
2231
|
+
* copy of the same mistake.
|
|
2232
|
+
*/
|
|
2233
|
+
export declare type StorageFieldType = 'string' | 'int' | 'bool' | 'password' | 'select';
|
|
2234
|
+
|
|
2235
|
+
/** A configured storage, as `GET /api/admin/storages` returns it. */
|
|
2236
|
+
export declare interface StorageRow {
|
|
2237
|
+
id: number;
|
|
2238
|
+
name: string;
|
|
2239
|
+
driver: string;
|
|
2240
|
+
enabled: boolean;
|
|
2241
|
+
read_only: boolean;
|
|
2242
|
+
config: Record<string, unknown>;
|
|
2243
|
+
rbac_enabled?: boolean;
|
|
2244
|
+
sync_mode?: string;
|
|
2245
|
+
created_at?: string;
|
|
2246
|
+
updated_at?: string;
|
|
2247
|
+
stats?: {
|
|
2248
|
+
file_count?: number;
|
|
2249
|
+
total_size_bytes?: number;
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
export declare interface StorageTestResult {
|
|
2254
|
+
ok: boolean;
|
|
2255
|
+
error?: string;
|
|
2256
|
+
object_count?: number;
|
|
2257
|
+
sample_listing?: unknown[];
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
/** POST/PATCH body for a storage. */
|
|
2261
|
+
export declare interface StorageWrite {
|
|
2262
|
+
name: string;
|
|
2263
|
+
driver: string;
|
|
2264
|
+
config: Record<string, unknown>;
|
|
2265
|
+
read_only?: boolean;
|
|
2266
|
+
enabled?: boolean;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
declare type Store = Record<string, ResumeRecord>;
|
|
2270
|
+
|
|
1566
2271
|
/**
|
|
1567
2272
|
* Create/update/empty the singleton `<style data-filex-theme>` element in
|
|
1568
2273
|
* <head>. Idempotent — safe to call from every explorer instance.
|
|
@@ -1662,9 +2367,43 @@ export declare const THEMES: ThemeDef[];
|
|
|
1662
2367
|
/** Map of `--fe-*` custom property → value. */
|
|
1663
2368
|
export declare type ThemeTokenMap = Record<string, string>;
|
|
1664
2369
|
|
|
2370
|
+
export declare const TokensPanel: DefineComponent<__VLS_Props_19, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
2371
|
+
active: (v: {
|
|
2372
|
+
hasToken: boolean;
|
|
2373
|
+
}) => any;
|
|
2374
|
+
}, string, PublicProps, Readonly<__VLS_Props_19> & Readonly<{
|
|
2375
|
+
onActive?: ((v: {
|
|
2376
|
+
hasToken: boolean;
|
|
2377
|
+
}) => any) | undefined;
|
|
2378
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
|
|
2379
|
+
|
|
1665
2380
|
/** Turkish UI strings. */
|
|
1666
2381
|
export declare const tr: Record<string, string>;
|
|
1667
2382
|
|
|
2383
|
+
/**
|
|
2384
|
+
* connectionGuides — "how do I connect to this thing?", generated from the
|
|
2385
|
+
* live deployment instead of written as prose.
|
|
2386
|
+
*
|
|
2387
|
+
* A published document says `https://fm.example.com/dav/` and leaves the
|
|
2388
|
+
* reader to substitute three values, one of which (their own username) they
|
|
2389
|
+
* usually get wrong. What ships here is the real host, the real storage
|
|
2390
|
+
* name and the caller's own credential, with a copy button — which is the
|
|
2391
|
+
* difference between a doc and a working paste. No surveyed product
|
|
2392
|
+
* (Backblaze, R2, Storj, MinIO, Garage) does this; it is the cheapest win
|
|
2393
|
+
* on the whole surface.
|
|
2394
|
+
*
|
|
2395
|
+
* Shape of the thing: a protocol is a `GuideBuilder` registered in
|
|
2396
|
+
* `GUIDE_BUILDERS`. WebDAV is built here because WebDAV is what filex
|
|
2397
|
+
* serves today; S3 and SFTP are a builder each and a registry line when
|
|
2398
|
+
* their servers land — no second implementation, no second UI.
|
|
2399
|
+
*
|
|
2400
|
+
* The commands are not invented. They are the ones verified on 2026-08-14
|
|
2401
|
+
* and written down in `docs/WEBDAV.md` and §13.5 of the write-path
|
|
2402
|
+
* handover, including the three Windows registry limits that otherwise
|
|
2403
|
+
* look exactly like filex bugs.
|
|
2404
|
+
*/
|
|
2405
|
+
export declare type Translate = (key: string, vars?: Record<string, string | number>) => string;
|
|
2406
|
+
|
|
1668
2407
|
/** A soft-deleted node as returned by the filex trash listing endpoint. */
|
|
1669
2408
|
declare interface TrashEntry {
|
|
1670
2409
|
id: number;
|
|
@@ -1683,6 +2422,13 @@ export declare interface UploadFinalizeResponse {
|
|
|
1683
2422
|
url?: string;
|
|
1684
2423
|
}
|
|
1685
2424
|
|
|
2425
|
+
/** Identity of one (destination, file) pair. */
|
|
2426
|
+
export declare function uploadFingerprint(path: string, file: {
|
|
2427
|
+
name: string;
|
|
2428
|
+
size: number;
|
|
2429
|
+
lastModified?: number;
|
|
2430
|
+
}): string;
|
|
2431
|
+
|
|
1686
2432
|
export declare interface UploadInitResponse {
|
|
1687
2433
|
uploadId: string;
|
|
1688
2434
|
parts: Array<{
|
|
@@ -1697,11 +2443,22 @@ export declare interface UploadJob {
|
|
|
1697
2443
|
id: string;
|
|
1698
2444
|
file: File;
|
|
1699
2445
|
path: string;
|
|
2446
|
+
/** Server-side staged upload id, once `begin` has answered. */
|
|
1700
2447
|
uploadId?: string;
|
|
1701
2448
|
totalBytes: number;
|
|
2449
|
+
/** Bytes filex has acknowledged (plus the chunk currently in flight). */
|
|
1702
2450
|
uploadedBytes: number;
|
|
1703
2451
|
percent: number;
|
|
1704
|
-
status: 'pending' | 'initializing' | 'uploading'
|
|
2452
|
+
status: 'pending' | 'initializing' | 'uploading'
|
|
2453
|
+
/** Every byte is in filex; the commit is being accepted. */
|
|
2454
|
+
| 'committing'
|
|
2455
|
+
/** Committed and listed; the ops worker is writing it to the backend. */
|
|
2456
|
+
| 'transferring' | 'done' | 'error' | 'aborted';
|
|
2457
|
+
/** Byte offset an interrupted session was picked up from, when it was. */
|
|
2458
|
+
resumedFrom?: number;
|
|
2459
|
+
/** Background transfer op, once the commit is accepted. */
|
|
2460
|
+
opId?: number;
|
|
2461
|
+
nodeId?: number;
|
|
1705
2462
|
error?: string;
|
|
1706
2463
|
cancel(): void;
|
|
1707
2464
|
}
|
|
@@ -1714,12 +2471,62 @@ export declare interface UploadOptions {
|
|
|
1714
2471
|
path: string;
|
|
1715
2472
|
file: File;
|
|
1716
2473
|
chunkSize?: number;
|
|
1717
|
-
parallelChunks?: number;
|
|
1718
2474
|
onProgress?: (job: UploadJob) => void;
|
|
1719
|
-
onDone?: (job: UploadJob, result:
|
|
2475
|
+
onDone?: (job: UploadJob, result: UploadResult) => void;
|
|
1720
2476
|
onError?: (job: UploadJob, err: Error) => void;
|
|
2477
|
+
/**
|
|
2478
|
+
* Wait for the backend transfer before resolving. Default false: the node is
|
|
2479
|
+
* listed the moment the commit is accepted, which is the whole point of
|
|
2480
|
+
* staging. `true` is for a caller that must not report success until the
|
|
2481
|
+
* bytes are on the driver.
|
|
2482
|
+
*/
|
|
2483
|
+
waitForTransfer?: boolean;
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
/** What `commit` answers, plus the fields a caller wants afterwards. */
|
|
2487
|
+
export declare interface UploadResult {
|
|
2488
|
+
id: string;
|
|
2489
|
+
op_id?: number;
|
|
2490
|
+
node_id?: number;
|
|
2491
|
+
path?: string;
|
|
2492
|
+
transfer_state?: string;
|
|
1721
2493
|
}
|
|
1722
2494
|
|
|
2495
|
+
export declare function useConnections(config: ExplorerConfig): {
|
|
2496
|
+
drivers: ShallowRef<StorageDriverDescriptor[], StorageDriverDescriptor[]>;
|
|
2497
|
+
driverNames: ComputedRef<string[]>;
|
|
2498
|
+
storages: ShallowRef<StorageRow[], StorageRow[]>;
|
|
2499
|
+
visible: ShallowRef<string[], string[]>;
|
|
2500
|
+
me: Ref< {
|
|
2501
|
+
id: number;
|
|
2502
|
+
email: string;
|
|
2503
|
+
display_name?: string | undefined;
|
|
2504
|
+
role?: string | undefined;
|
|
2505
|
+
} | null, ConnectionsUser | {
|
|
2506
|
+
id: number;
|
|
2507
|
+
email: string;
|
|
2508
|
+
display_name?: string | undefined;
|
|
2509
|
+
role?: string | undefined;
|
|
2510
|
+
} | null>;
|
|
2511
|
+
loading: Ref<boolean, boolean>;
|
|
2512
|
+
loaded: Ref<boolean, boolean>;
|
|
2513
|
+
error: Ref<string | null, string | null>;
|
|
2514
|
+
canManage: Ref<boolean | null, boolean | null>;
|
|
2515
|
+
denial: Ref<ManageDenial | null, ManageDenial | null>;
|
|
2516
|
+
load: () => Promise<void>;
|
|
2517
|
+
createStorage: (body: StorageWrite) => Promise<StorageRow>;
|
|
2518
|
+
updateStorage: (id: number, body: Partial<StorageWrite>) => Promise<StorageRow>;
|
|
2519
|
+
deleteStorage: (id: number) => Promise<void>;
|
|
2520
|
+
testStorage: (body: {
|
|
2521
|
+
driver: string;
|
|
2522
|
+
config: Record<string, unknown>;
|
|
2523
|
+
}) => Promise<StorageTestResult>;
|
|
2524
|
+
descriptor: (driver: string) => StorageDriverDescriptor | undefined;
|
|
2525
|
+
fields: (driver: string) => StorageField[];
|
|
2526
|
+
defaults: (driver: string) => Record<string, unknown>;
|
|
2527
|
+
missingRequired: (driver: string, cfg: Record<string, unknown>) => StorageField[];
|
|
2528
|
+
};
|
|
2529
|
+
|
|
1723
2530
|
export declare function useFileApi(config: ExplorerConfig): {
|
|
1724
2531
|
wsTicket: () => Promise<{
|
|
1725
2532
|
ticket: string;
|
|
@@ -1876,6 +2683,74 @@ export declare function useMonacoLoader(): {
|
|
|
1876
2683
|
getHighlight: typeof getHighlight;
|
|
1877
2684
|
};
|
|
1878
2685
|
|
|
2686
|
+
export declare function useNFSExports(config: ExplorerConfig): {
|
|
2687
|
+
exports: ShallowRef<NFSExport[], NFSExport[]>;
|
|
2688
|
+
connection: Ref< {
|
|
2689
|
+
enabled: boolean;
|
|
2690
|
+
host: string;
|
|
2691
|
+
port: number;
|
|
2692
|
+
} | null, NFSConnection | {
|
|
2693
|
+
enabled: boolean;
|
|
2694
|
+
host: string;
|
|
2695
|
+
port: number;
|
|
2696
|
+
} | null>;
|
|
2697
|
+
loading: Ref<boolean, boolean>;
|
|
2698
|
+
loaded: Ref<boolean, boolean>;
|
|
2699
|
+
error: Ref<string | null, string | null>;
|
|
2700
|
+
canMint: Ref<boolean | null, boolean | null>;
|
|
2701
|
+
revealed: Ref< {
|
|
2702
|
+
export: {
|
|
2703
|
+
id: number;
|
|
2704
|
+
user_id: number;
|
|
2705
|
+
api_token_id?: number | null | undefined;
|
|
2706
|
+
label: string;
|
|
2707
|
+
storage_name?: string | undefined;
|
|
2708
|
+
prefix?: string | undefined;
|
|
2709
|
+
read_only: boolean;
|
|
2710
|
+
allow_cidrs?: string | undefined;
|
|
2711
|
+
created_at: string;
|
|
2712
|
+
last_used_at?: string | null | undefined;
|
|
2713
|
+
expires_at?: string | null | undefined;
|
|
2714
|
+
disabled_at?: string | null | undefined;
|
|
2715
|
+
};
|
|
2716
|
+
path: string;
|
|
2717
|
+
enabled: boolean;
|
|
2718
|
+
host: string;
|
|
2719
|
+
port: number;
|
|
2720
|
+
} | null, NFSExportCreated | {
|
|
2721
|
+
export: {
|
|
2722
|
+
id: number;
|
|
2723
|
+
user_id: number;
|
|
2724
|
+
api_token_id?: number | null | undefined;
|
|
2725
|
+
label: string;
|
|
2726
|
+
storage_name?: string | undefined;
|
|
2727
|
+
prefix?: string | undefined;
|
|
2728
|
+
read_only: boolean;
|
|
2729
|
+
allow_cidrs?: string | undefined;
|
|
2730
|
+
created_at: string;
|
|
2731
|
+
last_used_at?: string | null | undefined;
|
|
2732
|
+
expires_at?: string | null | undefined;
|
|
2733
|
+
disabled_at?: string | null | undefined;
|
|
2734
|
+
};
|
|
2735
|
+
path: string;
|
|
2736
|
+
enabled: boolean;
|
|
2737
|
+
host: string;
|
|
2738
|
+
port: number;
|
|
2739
|
+
} | null>;
|
|
2740
|
+
guideExport: ComputedRef<NFSExport | null>;
|
|
2741
|
+
load: () => Promise<void>;
|
|
2742
|
+
create: (req: {
|
|
2743
|
+
label: string;
|
|
2744
|
+
storage?: string;
|
|
2745
|
+
prefix?: string;
|
|
2746
|
+
read_only?: boolean;
|
|
2747
|
+
allow_cidrs?: string;
|
|
2748
|
+
}) => Promise<NFSExportCreated | null>;
|
|
2749
|
+
setDisabled: (id: number, disabled: boolean) => Promise<void>;
|
|
2750
|
+
remove: (id: number) => Promise<void>;
|
|
2751
|
+
dismissPath: () => void;
|
|
2752
|
+
};
|
|
2753
|
+
|
|
1879
2754
|
export declare function useOperations(): {
|
|
1880
2755
|
active: Ref< {
|
|
1881
2756
|
key: string;
|
|
@@ -2009,6 +2884,66 @@ declare interface UserSuggestion {
|
|
|
2009
2884
|
role: string;
|
|
2010
2885
|
}
|
|
2011
2886
|
|
|
2887
|
+
export declare function useS3Keys(config: ExplorerConfig): {
|
|
2888
|
+
keys: ShallowRef<S3AccessKey[], S3AccessKey[]>;
|
|
2889
|
+
connection: Ref< {
|
|
2890
|
+
endpoint: string;
|
|
2891
|
+
enabled: boolean;
|
|
2892
|
+
path_style: boolean;
|
|
2893
|
+
} | null, S3Connection | {
|
|
2894
|
+
endpoint: string;
|
|
2895
|
+
enabled: boolean;
|
|
2896
|
+
path_style: boolean;
|
|
2897
|
+
} | null>;
|
|
2898
|
+
loading: Ref<boolean, boolean>;
|
|
2899
|
+
loaded: Ref<boolean, boolean>;
|
|
2900
|
+
error: Ref<string | null, string | null>;
|
|
2901
|
+
canMint: Ref<boolean | null, boolean | null>;
|
|
2902
|
+
revealed: Ref< {
|
|
2903
|
+
key: {
|
|
2904
|
+
id: number;
|
|
2905
|
+
access_key_id: string;
|
|
2906
|
+
user_id: number;
|
|
2907
|
+
api_token_id?: number | null | undefined;
|
|
2908
|
+
label: string;
|
|
2909
|
+
bucket?: string | undefined;
|
|
2910
|
+
prefix?: string | undefined;
|
|
2911
|
+
created_at: string;
|
|
2912
|
+
last_used_at?: string | null | undefined;
|
|
2913
|
+
expires_at?: string | null | undefined;
|
|
2914
|
+
disabled_at?: string | null | undefined;
|
|
2915
|
+
};
|
|
2916
|
+
secret: string;
|
|
2917
|
+
endpoint: string;
|
|
2918
|
+
enabled: boolean;
|
|
2919
|
+
path_style: boolean;
|
|
2920
|
+
} | null, S3KeyCreated | {
|
|
2921
|
+
key: {
|
|
2922
|
+
id: number;
|
|
2923
|
+
access_key_id: string;
|
|
2924
|
+
user_id: number;
|
|
2925
|
+
api_token_id?: number | null | undefined;
|
|
2926
|
+
label: string;
|
|
2927
|
+
bucket?: string | undefined;
|
|
2928
|
+
prefix?: string | undefined;
|
|
2929
|
+
created_at: string;
|
|
2930
|
+
last_used_at?: string | null | undefined;
|
|
2931
|
+
expires_at?: string | null | undefined;
|
|
2932
|
+
disabled_at?: string | null | undefined;
|
|
2933
|
+
};
|
|
2934
|
+
secret: string;
|
|
2935
|
+
endpoint: string;
|
|
2936
|
+
enabled: boolean;
|
|
2937
|
+
path_style: boolean;
|
|
2938
|
+
} | null>;
|
|
2939
|
+
guideKey: ComputedRef<S3AccessKey | null>;
|
|
2940
|
+
load: () => Promise<void>;
|
|
2941
|
+
create: (req: S3KeyRequest) => Promise<S3KeyCreated | null>;
|
|
2942
|
+
setDisabled: (id: number, disabled: boolean) => Promise<void>;
|
|
2943
|
+
remove: (id: number) => Promise<void>;
|
|
2944
|
+
dismissSecret: () => void;
|
|
2945
|
+
};
|
|
2946
|
+
|
|
2012
2947
|
export declare function useSelection(items: () => FileNode[]): {
|
|
2013
2948
|
selected: Ref<Set<string> & Omit<Set<string>, keyof Set<any>>, Set<string> | (Set<string> & Omit<Set<string>, keyof Set<any>>)>;
|
|
2014
2949
|
anchor: Ref<string | null, string | null>;
|
|
@@ -2029,6 +2964,46 @@ export declare function useSelection(items: () => FileNode[]): {
|
|
|
2029
2964
|
/** Reactive, override-aware view of the registry (registry order). */
|
|
2030
2965
|
export declare function useShortcutList(): ComputedRef<ShortcutView[]>;
|
|
2031
2966
|
|
|
2967
|
+
export declare function useSSHKeys(config: ExplorerConfig): {
|
|
2968
|
+
keys: ShallowRef<SSHPublicKey[], SSHPublicKey[]>;
|
|
2969
|
+
connection: Ref< {
|
|
2970
|
+
enabled: boolean;
|
|
2971
|
+
host: string;
|
|
2972
|
+
port: number;
|
|
2973
|
+
login: string;
|
|
2974
|
+
ftps?: {
|
|
2975
|
+
enabled: boolean;
|
|
2976
|
+
host: string;
|
|
2977
|
+
port: number;
|
|
2978
|
+
pasv_min: number;
|
|
2979
|
+
pasv_max: number;
|
|
2980
|
+
self_signed: boolean;
|
|
2981
|
+
} | undefined;
|
|
2982
|
+
} | null, SSHConnection | {
|
|
2983
|
+
enabled: boolean;
|
|
2984
|
+
host: string;
|
|
2985
|
+
port: number;
|
|
2986
|
+
login: string;
|
|
2987
|
+
ftps?: {
|
|
2988
|
+
enabled: boolean;
|
|
2989
|
+
host: string;
|
|
2990
|
+
port: number;
|
|
2991
|
+
pasv_min: number;
|
|
2992
|
+
pasv_max: number;
|
|
2993
|
+
self_signed: boolean;
|
|
2994
|
+
} | undefined;
|
|
2995
|
+
} | null>;
|
|
2996
|
+
loading: Ref<boolean, boolean>;
|
|
2997
|
+
loaded: Ref<boolean, boolean>;
|
|
2998
|
+
error: Ref<string | null, string | null>;
|
|
2999
|
+
canAdd: Ref<boolean | null, boolean | null>;
|
|
3000
|
+
hasUsableKey: ComputedRef<boolean>;
|
|
3001
|
+
load: () => Promise<void>;
|
|
3002
|
+
add: (key: string, name?: string) => Promise<boolean>;
|
|
3003
|
+
setDisabled: (id: number, disabled: boolean) => Promise<void>;
|
|
3004
|
+
remove: (id: number) => Promise<void>;
|
|
3005
|
+
};
|
|
3006
|
+
|
|
2032
3007
|
export declare function useTabs(opts: UseTabsOptions): {
|
|
2033
3008
|
tabs: Ref<TabState[], TabState[]>;
|
|
2034
3009
|
activeId: Ref<string, string>;
|
|
@@ -2061,8 +3036,52 @@ export declare function useThemeState(): {
|
|
|
2061
3036
|
setTheme: (id: string) => void;
|
|
2062
3037
|
};
|
|
2063
3038
|
|
|
2064
|
-
export declare function
|
|
2065
|
-
|
|
3039
|
+
export declare function useTokens(config: ExplorerConfig): {
|
|
3040
|
+
tokens: ShallowRef<ApiToken[], ApiToken[]>;
|
|
3041
|
+
loading: Ref<boolean, boolean>;
|
|
3042
|
+
loaded: Ref<boolean, boolean>;
|
|
3043
|
+
error: Ref<string | null, string | null>;
|
|
3044
|
+
canMint: Ref<boolean | null, boolean | null>;
|
|
3045
|
+
revealed: Ref< {
|
|
3046
|
+
token: string;
|
|
3047
|
+
row: {
|
|
3048
|
+
id: number;
|
|
3049
|
+
label: string;
|
|
3050
|
+
scopes: string;
|
|
3051
|
+
usernames?: string | null | undefined;
|
|
3052
|
+
created_at?: string | undefined;
|
|
3053
|
+
last_used_at?: string | null | undefined;
|
|
3054
|
+
expires_at?: string | null | undefined;
|
|
3055
|
+
};
|
|
3056
|
+
} | null, ApiTokenCreated | {
|
|
3057
|
+
token: string;
|
|
3058
|
+
row: {
|
|
3059
|
+
id: number;
|
|
3060
|
+
label: string;
|
|
3061
|
+
scopes: string;
|
|
3062
|
+
usernames?: string | null | undefined;
|
|
3063
|
+
created_at?: string | undefined;
|
|
3064
|
+
last_used_at?: string | null | undefined;
|
|
3065
|
+
expires_at?: string | null | undefined;
|
|
3066
|
+
};
|
|
3067
|
+
} | null>;
|
|
3068
|
+
load: () => Promise<void>;
|
|
3069
|
+
create: (req: ApiTokenRequest) => Promise<ApiTokenCreated | null>;
|
|
3070
|
+
remove: (id: number) => Promise<void>;
|
|
3071
|
+
dismiss: () => void;
|
|
3072
|
+
};
|
|
3073
|
+
|
|
3074
|
+
export declare function useUploadChunked(config: ExplorerConfig, api: FileApi, storage?: ResumeStorage | null): {
|
|
3075
|
+
uploadFile: (opts: UploadOptions) => Promise<UploadResult>;
|
|
3076
|
+
/** True when this file is big enough (and the endpoints exist) to chunk. */
|
|
3077
|
+
shouldChunk: (file: {
|
|
3078
|
+
size: number;
|
|
3079
|
+
}) => boolean;
|
|
3080
|
+
/** The size at which chunking kicks in. */
|
|
3081
|
+
threshold: () => number;
|
|
3082
|
+
resumableFor: (path: string, file: File) => ResumeRecord | null;
|
|
3083
|
+
listResumable: () => ResumeRecord[];
|
|
3084
|
+
discardResumable: (rec: ResumeRecord) => Promise<void>;
|
|
2066
3085
|
};
|
|
2067
3086
|
|
|
2068
3087
|
/**
|