@shhhum/xftp-web 0.1.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.
Files changed (74) hide show
  1. package/README.md +47 -0
  2. package/dist/agent.d.ts +46 -0
  3. package/dist/agent.js +273 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/client.d.ts +63 -0
  6. package/dist/client.js +353 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/crypto/digest.d.ts +3 -0
  9. package/dist/crypto/digest.js +23 -0
  10. package/dist/crypto/digest.js.map +1 -0
  11. package/dist/crypto/file.d.ts +14 -0
  12. package/dist/crypto/file.js +68 -0
  13. package/dist/crypto/file.js.map +1 -0
  14. package/dist/crypto/identity.d.ts +10 -0
  15. package/dist/crypto/identity.js +98 -0
  16. package/dist/crypto/identity.js.map +1 -0
  17. package/dist/crypto/keys.d.ts +27 -0
  18. package/dist/crypto/keys.js +138 -0
  19. package/dist/crypto/keys.js.map +1 -0
  20. package/dist/crypto/padding.d.ts +8 -0
  21. package/dist/crypto/padding.js +60 -0
  22. package/dist/crypto/padding.js.map +1 -0
  23. package/dist/crypto/secretbox.d.ts +22 -0
  24. package/dist/crypto/secretbox.js +195 -0
  25. package/dist/crypto/secretbox.js.map +1 -0
  26. package/dist/download.d.ts +9 -0
  27. package/dist/download.js +60 -0
  28. package/dist/download.js.map +1 -0
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +4 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/protocol/address.d.ts +7 -0
  33. package/dist/protocol/address.js +50 -0
  34. package/dist/protocol/address.js.map +1 -0
  35. package/dist/protocol/chunks.d.ts +15 -0
  36. package/dist/protocol/chunks.js +75 -0
  37. package/dist/protocol/chunks.js.map +1 -0
  38. package/dist/protocol/client.d.ts +9 -0
  39. package/dist/protocol/client.js +69 -0
  40. package/dist/protocol/client.js.map +1 -0
  41. package/dist/protocol/commands.d.ts +68 -0
  42. package/dist/protocol/commands.js +115 -0
  43. package/dist/protocol/commands.js.map +1 -0
  44. package/dist/protocol/description.d.ts +37 -0
  45. package/dist/protocol/description.js +317 -0
  46. package/dist/protocol/description.js.map +1 -0
  47. package/dist/protocol/encoding.d.ts +34 -0
  48. package/dist/protocol/encoding.js +197 -0
  49. package/dist/protocol/encoding.js.map +1 -0
  50. package/dist/protocol/handshake.d.ts +47 -0
  51. package/dist/protocol/handshake.js +158 -0
  52. package/dist/protocol/handshake.js.map +1 -0
  53. package/dist/protocol/transmission.d.ts +15 -0
  54. package/dist/protocol/transmission.js +84 -0
  55. package/dist/protocol/transmission.js.map +1 -0
  56. package/package.json +40 -0
  57. package/src/agent.ts +372 -0
  58. package/src/client.ts +448 -0
  59. package/src/crypto/digest.ts +26 -0
  60. package/src/crypto/file.ts +94 -0
  61. package/src/crypto/identity.ts +112 -0
  62. package/src/crypto/keys.ts +172 -0
  63. package/src/crypto/padding.ts +61 -0
  64. package/src/crypto/secretbox.ts +219 -0
  65. package/src/download.ts +76 -0
  66. package/src/index.ts +4 -0
  67. package/src/protocol/address.ts +54 -0
  68. package/src/protocol/chunks.ts +86 -0
  69. package/src/protocol/client.ts +95 -0
  70. package/src/protocol/commands.ts +157 -0
  71. package/src/protocol/description.ts +363 -0
  72. package/src/protocol/encoding.ts +224 -0
  73. package/src/protocol/handshake.ts +220 -0
  74. package/src/protocol/transmission.ts +113 -0
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # xftp-web
2
+
3
+ Browser-compatible XFTP file transfer client in TypeScript.
4
+
5
+ ## Prerequisites
6
+
7
+ - Haskell toolchain with `cabal` (to build `xftp-server`)
8
+ - Node.js 20+
9
+ - Chromium system dependencies (see below)
10
+
11
+ ## Setup
12
+
13
+ ```bash
14
+ # Build the XFTP server binary (from repo root)
15
+ cabal build xftp-server
16
+
17
+ # Install JS dependencies
18
+ cd xftp-web
19
+ npm install
20
+
21
+ # Install Chromium for Playwright (browser tests)
22
+ npx playwright install chromium
23
+ ```
24
+
25
+ If Chromium fails to launch due to missing system libraries, install them with:
26
+
27
+ ```bash
28
+ # Requires root
29
+ npx playwright install-deps chromium
30
+ ```
31
+
32
+ ## Running tests
33
+
34
+ ```bash
35
+ # Browser round-trip test (vitest + Playwright headless Chromium)
36
+ npm run test
37
+ ```
38
+
39
+ The browser test automatically starts an `xftp-server` instance on port 7000 via `globalSetup`, using certs from `tests/fixtures/`.
40
+
41
+ ## Build
42
+
43
+ ```bash
44
+ npm run build
45
+ ```
46
+
47
+ Output goes to `dist/`.
@@ -0,0 +1,46 @@
1
+ import { type FileDescription } from "./protocol/description.js";
2
+ import { type XFTPClientAgent } from "./client.js";
3
+ export { newXFTPAgent, closeXFTPAgent, type XFTPClientAgent, type TransportConfig } from "./client.js";
4
+ import type { XFTPServer } from "./protocol/address.js";
5
+ import type { FileHeader } from "./crypto/file.js";
6
+ export interface EncryptedFileMetadata {
7
+ digest: Uint8Array;
8
+ key: Uint8Array;
9
+ nonce: Uint8Array;
10
+ chunkSizes: number[];
11
+ }
12
+ export interface EncryptedFileInfo extends EncryptedFileMetadata {
13
+ encData: Uint8Array;
14
+ }
15
+ export interface UploadResult {
16
+ rcvDescription: FileDescription;
17
+ sndDescription: FileDescription;
18
+ uri: string;
19
+ }
20
+ export interface DownloadResult {
21
+ header: FileHeader;
22
+ content: Uint8Array;
23
+ }
24
+ export declare function encodeDescriptionURI(fd: FileDescription): string;
25
+ export declare function decodeDescriptionURI(fragment: string): FileDescription;
26
+ export declare function encryptFileForUpload(source: Uint8Array, fileName: string): EncryptedFileInfo;
27
+ export interface UploadOptions {
28
+ onProgress?: (uploaded: number, total: number) => void;
29
+ redirectThreshold?: number;
30
+ readChunk?: (offset: number, size: number) => Promise<Uint8Array>;
31
+ }
32
+ export declare function uploadFile(agent: XFTPClientAgent, server: XFTPServer, encrypted: EncryptedFileMetadata, options?: UploadOptions): Promise<UploadResult>;
33
+ export interface RawDownloadedChunk {
34
+ chunkNo: number;
35
+ dhSecret: Uint8Array;
36
+ nonce: Uint8Array;
37
+ body: Uint8Array;
38
+ digest: Uint8Array;
39
+ }
40
+ export interface DownloadRawOptions {
41
+ onProgress?: (downloaded: number, total: number) => void;
42
+ concurrency?: number;
43
+ }
44
+ export declare function downloadFileRaw(agent: XFTPClientAgent, fd: FileDescription, onRawChunk: (chunk: RawDownloadedChunk) => Promise<void>, options?: DownloadRawOptions): Promise<FileDescription>;
45
+ export declare function downloadFile(agent: XFTPClientAgent, fd: FileDescription, onProgress?: (downloaded: number, total: number) => void): Promise<DownloadResult>;
46
+ export declare function deleteFile(agent: XFTPClientAgent, sndDescription: FileDescription): Promise<void>;
package/dist/agent.js ADDED
@@ -0,0 +1,273 @@
1
+ // XFTP upload/download orchestration + URI encoding -- Simplex.FileTransfer.Client.Main
2
+ //
3
+ // Combines all building blocks: encryption, chunking, XFTP client commands,
4
+ // file descriptions, and DEFLATE-compressed URI encoding.
5
+ import pako from "pako";
6
+ import { encryptFile, encodeFileHeader } from "./crypto/file.js";
7
+ import { generateEd25519KeyPair, encodePubKeyEd25519, encodePrivKeyEd25519, decodePrivKeyEd25519, ed25519KeyPairFromSeed } from "./crypto/keys.js";
8
+ import { sha512Streaming } from "./crypto/digest.js";
9
+ import { prepareChunkSizes, prepareChunkSpecs, getChunkDigest, fileSizeLen, authTagSize } from "./protocol/chunks.js";
10
+ import { encodeFileDescription, decodeFileDescription, validateFileDescription, base64urlEncode, base64urlDecode } from "./protocol/description.js";
11
+ import { createXFTPChunk, uploadXFTPChunk, downloadXFTPChunk, downloadXFTPChunkRaw, deleteXFTPChunk } from "./client.js";
12
+ export { newXFTPAgent, closeXFTPAgent } from "./client.js";
13
+ import { processDownloadedFile, decryptReceivedChunk } from "./download.js";
14
+ import { formatXFTPServer, parseXFTPServer } from "./protocol/address.js";
15
+ // -- URI encoding/decoding (RFC section 4.1: DEFLATE + base64url)
16
+ export function encodeDescriptionURI(fd) {
17
+ const yaml = encodeFileDescription(fd);
18
+ const compressed = pako.deflateRaw(new TextEncoder().encode(yaml));
19
+ return base64urlEncode(compressed);
20
+ }
21
+ export function decodeDescriptionURI(fragment) {
22
+ const compressed = base64urlDecode(fragment);
23
+ const yaml = new TextDecoder().decode(pako.inflateRaw(compressed));
24
+ const fd = decodeFileDescription(yaml);
25
+ const err = validateFileDescription(fd);
26
+ if (err)
27
+ throw new Error("decodeDescriptionURI: " + err);
28
+ return fd;
29
+ }
30
+ // -- Upload
31
+ export function encryptFileForUpload(source, fileName) {
32
+ const key = new Uint8Array(32);
33
+ const nonce = new Uint8Array(24);
34
+ crypto.getRandomValues(key);
35
+ crypto.getRandomValues(nonce);
36
+ const fileHdr = encodeFileHeader({ fileName, fileExtra: null });
37
+ const fileSize = BigInt(fileHdr.length + source.length);
38
+ const payloadSize = Number(fileSize) + fileSizeLen + authTagSize;
39
+ const chunkSizes = prepareChunkSizes(payloadSize);
40
+ const encSize = BigInt(chunkSizes.reduce((a, b) => a + b, 0));
41
+ const encData = encryptFile(source, fileHdr, key, nonce, fileSize, encSize);
42
+ const digest = sha512Streaming([encData]);
43
+ console.log(`[AGENT-DBG] encrypt: encData.len=${encData.length} digest=${_dbgHex(digest, 64)} chunkSizes=[${chunkSizes.join(',')}]`);
44
+ return { encData, digest, key, nonce, chunkSizes };
45
+ }
46
+ const DEFAULT_REDIRECT_THRESHOLD = 400;
47
+ export async function uploadFile(agent, server, encrypted, options) {
48
+ const { onProgress, redirectThreshold, readChunk: readChunkOpt } = options ?? {};
49
+ const readChunk = readChunkOpt
50
+ ? readChunkOpt
51
+ : ('encData' in encrypted
52
+ ? (off, sz) => Promise.resolve(encrypted.encData.subarray(off, off + sz))
53
+ : () => { throw new Error("uploadFile: readChunk required when encData is absent"); });
54
+ const total = encrypted.chunkSizes.reduce((a, b) => a + b, 0);
55
+ const specs = prepareChunkSpecs(encrypted.chunkSizes);
56
+ const sentChunks = [];
57
+ let uploaded = 0;
58
+ for (let i = 0; i < specs.length; i++) {
59
+ const spec = specs[i];
60
+ const chunkNo = i + 1;
61
+ const sndKp = generateEd25519KeyPair();
62
+ const rcvKp = generateEd25519KeyPair();
63
+ const chunkData = await readChunk(spec.chunkOffset, spec.chunkSize);
64
+ const chunkDigest = getChunkDigest(chunkData);
65
+ console.log(`[AGENT-DBG] upload chunk=${chunkNo} offset=${spec.chunkOffset} size=${spec.chunkSize} digest=${_dbgHex(chunkDigest, 32)} data[0..8]=${_dbgHex(chunkData)} data[-8..]=${_dbgHex(chunkData.slice(-8))}`);
66
+ const fileInfo = {
67
+ sndKey: encodePubKeyEd25519(sndKp.publicKey),
68
+ size: spec.chunkSize,
69
+ digest: chunkDigest
70
+ };
71
+ const rcvKeysForChunk = [encodePubKeyEd25519(rcvKp.publicKey)];
72
+ const { senderId, recipientIds } = await createXFTPChunk(agent, server, sndKp.privateKey, fileInfo, rcvKeysForChunk);
73
+ await uploadXFTPChunk(agent, server, sndKp.privateKey, senderId, chunkData);
74
+ sentChunks.push({
75
+ chunkNo, senderId, senderKey: sndKp.privateKey,
76
+ recipientId: recipientIds[0], recipientKey: rcvKp.privateKey,
77
+ chunkSize: spec.chunkSize, digest: chunkDigest, server
78
+ });
79
+ uploaded += spec.chunkSize;
80
+ onProgress?.(uploaded, total);
81
+ }
82
+ const rcvDescription = buildDescription("recipient", encrypted, sentChunks);
83
+ const sndDescription = buildDescription("sender", encrypted, sentChunks);
84
+ let uri = encodeDescriptionURI(rcvDescription);
85
+ let finalRcvDescription = rcvDescription;
86
+ const threshold = redirectThreshold ?? DEFAULT_REDIRECT_THRESHOLD;
87
+ if (uri.length > threshold && sentChunks.length > 1) {
88
+ finalRcvDescription = await uploadRedirectDescription(agent, server, rcvDescription);
89
+ uri = encodeDescriptionURI(finalRcvDescription);
90
+ }
91
+ return { rcvDescription: finalRcvDescription, sndDescription, uri };
92
+ }
93
+ function buildDescription(party, enc, chunks) {
94
+ const defChunkSize = enc.chunkSizes[0];
95
+ return {
96
+ party,
97
+ size: enc.chunkSizes.reduce((a, b) => a + b, 0),
98
+ digest: enc.digest,
99
+ key: enc.key,
100
+ nonce: enc.nonce,
101
+ chunkSize: defChunkSize,
102
+ chunks: chunks.map(c => ({
103
+ chunkNo: c.chunkNo,
104
+ chunkSize: c.chunkSize,
105
+ digest: c.digest,
106
+ replicas: [{
107
+ server: formatXFTPServer(c.server),
108
+ replicaId: party === "recipient" ? c.recipientId : c.senderId,
109
+ replicaKey: encodePrivKeyEd25519(party === "recipient" ? c.recipientKey : c.senderKey)
110
+ }]
111
+ })),
112
+ redirect: null
113
+ };
114
+ }
115
+ async function uploadRedirectDescription(agent, server, innerFd) {
116
+ const yaml = encodeFileDescription(innerFd);
117
+ const yamlBytes = new TextEncoder().encode(yaml);
118
+ const enc = encryptFileForUpload(yamlBytes, "");
119
+ const specs = prepareChunkSpecs(enc.chunkSizes);
120
+ const sentChunks = [];
121
+ for (let i = 0; i < specs.length; i++) {
122
+ const spec = specs[i];
123
+ const chunkNo = i + 1;
124
+ const sndKp = generateEd25519KeyPair();
125
+ const rcvKp = generateEd25519KeyPair();
126
+ const chunkData = enc.encData.subarray(spec.chunkOffset, spec.chunkOffset + spec.chunkSize);
127
+ const chunkDigest = getChunkDigest(chunkData);
128
+ const fileInfo = {
129
+ sndKey: encodePubKeyEd25519(sndKp.publicKey),
130
+ size: spec.chunkSize,
131
+ digest: chunkDigest
132
+ };
133
+ const rcvKeysForChunk = [encodePubKeyEd25519(rcvKp.publicKey)];
134
+ const { senderId, recipientIds } = await createXFTPChunk(agent, server, sndKp.privateKey, fileInfo, rcvKeysForChunk);
135
+ await uploadXFTPChunk(agent, server, sndKp.privateKey, senderId, chunkData);
136
+ sentChunks.push({
137
+ chunkNo, senderId, senderKey: sndKp.privateKey,
138
+ recipientId: recipientIds[0], recipientKey: rcvKp.privateKey,
139
+ chunkSize: spec.chunkSize, digest: chunkDigest, server
140
+ });
141
+ }
142
+ return {
143
+ party: "recipient",
144
+ size: enc.chunkSizes.reduce((a, b) => a + b, 0),
145
+ digest: enc.digest,
146
+ key: enc.key,
147
+ nonce: enc.nonce,
148
+ chunkSize: enc.chunkSizes[0],
149
+ chunks: sentChunks.map(c => ({
150
+ chunkNo: c.chunkNo,
151
+ chunkSize: c.chunkSize,
152
+ digest: c.digest,
153
+ replicas: [{
154
+ server: formatXFTPServer(c.server),
155
+ replicaId: c.recipientId,
156
+ replicaKey: encodePrivKeyEd25519(c.recipientKey)
157
+ }]
158
+ })),
159
+ redirect: { size: innerFd.size, digest: innerFd.digest }
160
+ };
161
+ }
162
+ export async function downloadFileRaw(agent, fd, onRawChunk, options) {
163
+ const err = validateFileDescription(fd);
164
+ if (err)
165
+ throw new Error("downloadFileRaw: " + err);
166
+ const { onProgress, concurrency = 1 } = options ?? {};
167
+ // Resolve redirect on main thread (redirect data is small)
168
+ if (fd.redirect !== null) {
169
+ console.log(`[AGENT-DBG] resolving redirect: outer size=${fd.size} chunks=${fd.chunks.length}`);
170
+ fd = await resolveRedirect(agent, fd);
171
+ console.log(`[AGENT-DBG] resolved: size=${fd.size} chunks=${fd.chunks.length} digest=${Array.from(fd.digest.slice(0, 16)).map(x => x.toString(16).padStart(2, '0')).join('')}…`);
172
+ }
173
+ const resolvedFd = fd;
174
+ // Group chunks by server, sequential within each server, parallel across servers
175
+ let downloaded = 0;
176
+ const byServer = new Map();
177
+ for (const chunk of resolvedFd.chunks) {
178
+ const srv = chunk.replicas[0]?.server ?? "";
179
+ if (!byServer.has(srv))
180
+ byServer.set(srv, []);
181
+ byServer.get(srv).push(chunk);
182
+ }
183
+ await Promise.all([...byServer.entries()].map(async ([srv, chunks]) => {
184
+ const server = parseXFTPServer(srv);
185
+ for (const chunk of chunks) {
186
+ const replica = chunk.replicas[0];
187
+ if (!replica)
188
+ throw new Error("downloadFileRaw: chunk has no replicas");
189
+ const seed = decodePrivKeyEd25519(replica.replicaKey);
190
+ const kp = ed25519KeyPairFromSeed(seed);
191
+ const raw = await downloadXFTPChunkRaw(agent, server, kp.privateKey, replica.replicaId);
192
+ console.log(`[AGENT-DBG] chunk=${chunk.chunkNo} body.len=${raw.body.length} expectedChunkSize=${chunk.chunkSize} digest=${_dbgHex(chunk.digest, 32)} body.byteOffset=${raw.body.byteOffset} body.buffer.byteLength=${raw.body.buffer.byteLength}`);
193
+ await onRawChunk({
194
+ chunkNo: chunk.chunkNo,
195
+ dhSecret: raw.dhSecret,
196
+ nonce: raw.nonce,
197
+ body: raw.body,
198
+ digest: chunk.digest
199
+ });
200
+ downloaded += chunk.chunkSize;
201
+ onProgress?.(downloaded, resolvedFd.size);
202
+ }
203
+ }));
204
+ return resolvedFd;
205
+ }
206
+ export async function downloadFile(agent, fd, onProgress) {
207
+ const chunks = [];
208
+ const resolvedFd = await downloadFileRaw(agent, fd, async (raw) => {
209
+ chunks[raw.chunkNo - 1] = decryptReceivedChunk(raw.dhSecret, raw.nonce, raw.body, raw.digest);
210
+ }, { onProgress });
211
+ const totalSize = chunks.reduce((s, c) => s + c.length, 0);
212
+ if (totalSize !== resolvedFd.size)
213
+ throw new Error("downloadFile: file size mismatch");
214
+ const digest = sha512Streaming(chunks);
215
+ if (!digestEqual(digest, resolvedFd.digest))
216
+ throw new Error("downloadFile: file digest mismatch");
217
+ return processDownloadedFile(resolvedFd, chunks);
218
+ }
219
+ async function resolveRedirect(agent, fd) {
220
+ const plaintextChunks = new Array(fd.chunks.length);
221
+ for (const chunk of fd.chunks) {
222
+ const replica = chunk.replicas[0];
223
+ if (!replica)
224
+ throw new Error("resolveRedirect: chunk has no replicas");
225
+ const server = parseXFTPServer(replica.server);
226
+ const seed = decodePrivKeyEd25519(replica.replicaKey);
227
+ const kp = ed25519KeyPairFromSeed(seed);
228
+ const data = await downloadXFTPChunk(agent, server, kp.privateKey, replica.replicaId, chunk.digest);
229
+ plaintextChunks[chunk.chunkNo - 1] = data;
230
+ }
231
+ const totalSize = plaintextChunks.reduce((s, c) => s + c.length, 0);
232
+ if (totalSize !== fd.size)
233
+ throw new Error("resolveRedirect: redirect file size mismatch");
234
+ const digest = sha512Streaming(plaintextChunks);
235
+ if (!digestEqual(digest, fd.digest))
236
+ throw new Error("resolveRedirect: redirect file digest mismatch");
237
+ const { content: yamlBytes } = processDownloadedFile(fd, plaintextChunks);
238
+ const yamlStr = new TextDecoder().decode(yamlBytes);
239
+ const innerFd = decodeFileDescription(yamlStr);
240
+ const innerErr = validateFileDescription(innerFd);
241
+ if (innerErr)
242
+ throw new Error("resolveRedirect: inner description invalid: " + innerErr);
243
+ if (innerFd.size !== fd.redirect.size)
244
+ throw new Error("resolveRedirect: redirect size mismatch");
245
+ if (!digestEqual(innerFd.digest, fd.redirect.digest))
246
+ throw new Error("resolveRedirect: redirect digest mismatch");
247
+ return innerFd;
248
+ }
249
+ // -- Delete
250
+ export async function deleteFile(agent, sndDescription) {
251
+ for (const chunk of sndDescription.chunks) {
252
+ const replica = chunk.replicas[0];
253
+ if (!replica)
254
+ throw new Error("deleteFile: chunk has no replicas");
255
+ const server = parseXFTPServer(replica.server);
256
+ const seed = decodePrivKeyEd25519(replica.replicaKey);
257
+ const kp = ed25519KeyPairFromSeed(seed);
258
+ await deleteXFTPChunk(agent, server, kp.privateKey, replica.replicaId);
259
+ }
260
+ }
261
+ // -- Internal
262
+ function _dbgHex(b, n = 8) {
263
+ return Array.from(b.slice(0, n)).map(x => x.toString(16).padStart(2, '0')).join('');
264
+ }
265
+ function digestEqual(a, b) {
266
+ if (a.length !== b.length)
267
+ return false;
268
+ let diff = 0;
269
+ for (let i = 0; i < a.length; i++)
270
+ diff |= a[i] ^ b[i];
271
+ return diff === 0;
272
+ }
273
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { type FileResponse, type FileInfo, type XFTPErrorType } from "./protocol/commands.js";
2
+ import type { XFTPServer } from "./protocol/address.js";
3
+ export declare class XFTPRetriableError extends Error {
4
+ readonly errorType: string;
5
+ constructor(errorType: string);
6
+ }
7
+ export declare class XFTPPermanentError extends Error {
8
+ readonly errorType: string;
9
+ constructor(errorType: string, message: string);
10
+ }
11
+ export declare function isRetriable(e: unknown): boolean;
12
+ export declare function categorizeError(e: unknown): Error;
13
+ export declare function humanReadableMessage(errorType: string | XFTPErrorType): string;
14
+ export interface XFTPClient {
15
+ baseUrl: string;
16
+ sessionId: Uint8Array;
17
+ xftpVersion: number;
18
+ transport: Transport;
19
+ }
20
+ export interface TransportConfig {
21
+ timeoutMs: number;
22
+ }
23
+ interface Transport {
24
+ post(body: Uint8Array, headers?: Record<string, string>): Promise<Uint8Array>;
25
+ close(): void;
26
+ }
27
+ interface ServerConnection {
28
+ client: Promise<XFTPClient>;
29
+ queue: Promise<void>;
30
+ }
31
+ export interface XFTPClientAgent {
32
+ connections: Map<string, ServerConnection>;
33
+ /** @internal Injectable for testing — defaults to connectXFTP */
34
+ _connectFn: (server: XFTPServer) => Promise<XFTPClient>;
35
+ }
36
+ export declare function newXFTPAgent(): XFTPClientAgent;
37
+ export declare function getXFTPServerClient(agent: XFTPClientAgent, server: XFTPServer): Promise<XFTPClient>;
38
+ export declare function reconnectClient(agent: XFTPClientAgent, server: XFTPServer): Promise<XFTPClient>;
39
+ export declare function removeStaleConnection(agent: XFTPClientAgent, server: XFTPServer, failedP: Promise<XFTPClient>): void;
40
+ export declare function closeXFTPServerClient(agent: XFTPClientAgent, server: XFTPServer): void;
41
+ export declare function closeXFTPAgent(agent: XFTPClientAgent): void;
42
+ export declare function connectXFTP(server: XFTPServer, config?: Partial<TransportConfig>): Promise<XFTPClient>;
43
+ export declare function sendXFTPCommand(agent: XFTPClientAgent, server: XFTPServer, privateKey: Uint8Array, entityId: Uint8Array, cmdBytes: Uint8Array, chunkData?: Uint8Array, maxRetries?: number): Promise<{
44
+ response: FileResponse;
45
+ body: Uint8Array;
46
+ }>;
47
+ export declare function createXFTPChunk(agent: XFTPClientAgent, server: XFTPServer, spKey: Uint8Array, file: FileInfo, rcvKeys: Uint8Array[], auth?: Uint8Array | null): Promise<{
48
+ senderId: Uint8Array;
49
+ recipientIds: Uint8Array[];
50
+ }>;
51
+ export declare function addXFTPRecipients(agent: XFTPClientAgent, server: XFTPServer, spKey: Uint8Array, fId: Uint8Array, rcvKeys: Uint8Array[]): Promise<Uint8Array[]>;
52
+ export declare function uploadXFTPChunk(agent: XFTPClientAgent, server: XFTPServer, spKey: Uint8Array, fId: Uint8Array, chunkData: Uint8Array): Promise<void>;
53
+ export interface RawChunkResponse {
54
+ dhSecret: Uint8Array;
55
+ nonce: Uint8Array;
56
+ body: Uint8Array;
57
+ }
58
+ export declare function downloadXFTPChunkRaw(agent: XFTPClientAgent, server: XFTPServer, rpKey: Uint8Array, fId: Uint8Array): Promise<RawChunkResponse>;
59
+ export declare function downloadXFTPChunk(agent: XFTPClientAgent, server: XFTPServer, rpKey: Uint8Array, fId: Uint8Array, digest?: Uint8Array): Promise<Uint8Array>;
60
+ export declare function deleteXFTPChunk(agent: XFTPClientAgent, server: XFTPServer, spKey: Uint8Array, sId: Uint8Array): Promise<void>;
61
+ export declare function pingXFTP(agent: XFTPClientAgent, server: XFTPServer): Promise<void>;
62
+ export declare function closeXFTP(c: XFTPClient): void;
63
+ export {};