@dropgate/core 2.2.0 â 3.0.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 +259 -128
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +2814 -1436
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +424 -283
- package/dist/index.d.ts +424 -283
- package/dist/index.js +2816 -1389
- package/dist/index.js.map +1 -1
- package/dist/p2p/index.cjs +495 -190
- package/dist/p2p/index.cjs.map +1 -1
- package/dist/p2p/index.d.cts +366 -5
- package/dist/p2p/index.d.ts +366 -5
- package/dist/p2p/index.js +497 -178
- package/dist/p2p/index.js.map +1 -1
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<div align="center">
|
|
10
10
|
|
|
11
11
|

|
|
12
|
-

|
|
13
13
|

|
|
14
14
|
|
|
15
15
|
[](https://diamonddigital.dev/discord)
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Overview
|
|
21
21
|
|
|
22
22
|
**@dropgate/core** is the universal client library for Dropgate. It provides all the core functionality for:
|
|
23
23
|
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
- Downloading files from Dropgate servers
|
|
26
26
|
- Direct peer-to-peer file transfers (P2P)
|
|
27
27
|
- Server capability detection and version checking
|
|
28
|
-
- Utility functions for
|
|
28
|
+
- Utility functions for lifetime conversions, base64 encoding, and more
|
|
29
29
|
|
|
30
30
|
This package is **headless** and **environment-agnostic** â it contains no DOM manipulation, no browser-specific APIs, and no Node.js-specific code. All environment-specific concerns (loading PeerJS, handling file streams, etc.) are handled by the consumer.
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Installation
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
npm install @dropgate/core
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Builds
|
|
39
39
|
|
|
40
40
|
The package ships with multiple build targets:
|
|
41
41
|
|
|
@@ -45,144 +45,174 @@ The package ships with multiple build targets:
|
|
|
45
45
|
| CJS | `dist/index.cjs` | Legacy Node.js, CommonJS |
|
|
46
46
|
| Browser IIFE | `dist/index.browser.js` | `<script>` tag, exposes `DropgateCore` global |
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## Quick Start
|
|
49
49
|
|
|
50
|
-
###
|
|
50
|
+
### Configure Once, Use Everywhere
|
|
51
|
+
|
|
52
|
+
All operations go through a single `DropgateClient` instance. Server connection details are specified once in the constructor:
|
|
51
53
|
|
|
52
54
|
```javascript
|
|
53
55
|
import { DropgateClient } from '@dropgate/core';
|
|
54
56
|
|
|
55
|
-
const client = new DropgateClient({
|
|
57
|
+
const client = new DropgateClient({
|
|
58
|
+
clientVersion: '3.0.0',
|
|
59
|
+
server: 'https://dropgate.link', // URL string or { host, port?, secure? }
|
|
60
|
+
fallbackToHttp: true, // auto-retry HTTP if HTTPS fails (optional)
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Connecting to the Server
|
|
65
|
+
|
|
66
|
+
`connect()` fetches server info, checks version compatibility, and caches the result. All methods call `connect()` internally, so explicit calls are optional â useful for "Test Connection" buttons or eager validation.
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
const { serverInfo, compatible, message } = await client.connect({ timeoutMs: 5000 });
|
|
70
|
+
|
|
71
|
+
console.log('Server version:', serverInfo.version);
|
|
72
|
+
console.log('Compatible:', compatible);
|
|
73
|
+
console.log('Upload enabled:', serverInfo.capabilities?.upload?.enabled);
|
|
74
|
+
console.log('P2P enabled:', serverInfo.capabilities?.p2p?.enabled);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Uploading Files
|
|
56
78
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
secure: true,
|
|
61
|
-
file: myFile, // File or Blob
|
|
79
|
+
```javascript
|
|
80
|
+
const session = await client.uploadFiles({
|
|
81
|
+
file: myFile, // File or Blob (implements FileSource)
|
|
62
82
|
lifetimeMs: 3600000, // 1 hour
|
|
63
|
-
maxDownloads: 5,
|
|
83
|
+
maxDownloads: 5,
|
|
64
84
|
encrypt: true,
|
|
65
85
|
onProgress: ({ phase, text, percent }) => {
|
|
66
|
-
console.log(`${phase}: ${text} (${percent
|
|
86
|
+
console.log(`${phase}: ${text} (${percent ?? 0}%)`);
|
|
67
87
|
},
|
|
68
88
|
});
|
|
69
89
|
|
|
90
|
+
const result = await session.result;
|
|
70
91
|
console.log('Download URL:', result.downloadUrl);
|
|
92
|
+
|
|
93
|
+
// Cancel an in-progress upload:
|
|
94
|
+
// session.cancel('User cancelled');
|
|
71
95
|
```
|
|
72
96
|
|
|
73
|
-
###
|
|
97
|
+
### Fetching File/Bundle Metadata
|
|
74
98
|
|
|
75
99
|
```javascript
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
100
|
+
// Fetch file metadata (size, encryption status, filename)
|
|
101
|
+
const fileMeta = await client.getFileMetadata('file-id-123');
|
|
102
|
+
console.log('File size:', fileMeta.sizeBytes);
|
|
103
|
+
console.log('Encrypted:', fileMeta.isEncrypted);
|
|
104
|
+
console.log('Filename:', fileMeta.filename || fileMeta.encryptedFilename);
|
|
105
|
+
|
|
106
|
+
// Fetch bundle metadata with automatic derivation
|
|
107
|
+
const bundleMeta = await client.getBundleMetadata(
|
|
108
|
+
'bundle-id-456',
|
|
109
|
+
'base64-key-from-url-hash' // Required for encrypted bundles
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
console.log('Files:', bundleMeta.fileCount);
|
|
113
|
+
console.log('Total size:', bundleMeta.totalSizeBytes);
|
|
114
|
+
console.log('Sealed:', bundleMeta.sealed);
|
|
115
|
+
|
|
116
|
+
// For sealed bundles, the manifest is automatically decrypted
|
|
117
|
+
// and files array is populated from the decrypted manifest
|
|
118
|
+
bundleMeta.files.forEach(file => {
|
|
119
|
+
console.log(`- ${file.filename}: ${file.sizeBytes} bytes`);
|
|
82
120
|
});
|
|
83
|
-
|
|
84
|
-
console.log('Server version:', serverInfo.version);
|
|
85
|
-
console.log('Upload enabled:', serverInfo.capabilities?.upload?.enabled);
|
|
86
|
-
console.log('P2P enabled:', serverInfo.capabilities?.p2p?.enabled);
|
|
87
121
|
```
|
|
88
122
|
|
|
89
|
-
###
|
|
123
|
+
### Downloading Files
|
|
90
124
|
|
|
91
125
|
```javascript
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
126
|
+
// Download with streaming (for large files)
|
|
127
|
+
const result = await client.downloadFiles({
|
|
128
|
+
fileId: 'abc123',
|
|
129
|
+
keyB64: 'base64-key-from-url-hash', // Required for encrypted files
|
|
130
|
+
onProgress: ({ phase, percent, processedBytes, totalBytes }) => {
|
|
131
|
+
console.log(`${phase}: ${percent}% (${processedBytes}/${totalBytes})`);
|
|
132
|
+
},
|
|
133
|
+
onData: async (chunk) => {
|
|
134
|
+
await writer.write(chunk);
|
|
135
|
+
},
|
|
101
136
|
});
|
|
102
137
|
|
|
103
|
-
console.log('
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
console.log('Server capabilities:', compat.serverInfo.capabilities);
|
|
138
|
+
console.log('Downloaded:', result.filename);
|
|
139
|
+
|
|
140
|
+
// Or download to memory (for small files â omit onData)
|
|
141
|
+
const memoryResult = await client.downloadFiles({ fileId: 'abc123' });
|
|
142
|
+
console.log('File size:', memoryResult.data?.length);
|
|
109
143
|
```
|
|
110
144
|
|
|
111
|
-
###
|
|
145
|
+
### P2P File Transfer (Sender)
|
|
112
146
|
|
|
113
147
|
```javascript
|
|
114
|
-
import { startP2PSend } from '@dropgate/core';
|
|
115
|
-
|
|
116
|
-
// Consumer must provide PeerJS Peer constructor
|
|
117
148
|
const Peer = await loadPeerJS(); // Your loader function
|
|
118
149
|
|
|
119
|
-
const session = await
|
|
150
|
+
const session = await client.p2pSend({
|
|
120
151
|
file: myFile,
|
|
121
152
|
Peer,
|
|
122
|
-
host: 'dropgate.link',
|
|
123
|
-
port: 443,
|
|
124
|
-
secure: true,
|
|
125
153
|
onCode: (code) => console.log('Share this code:', code),
|
|
126
154
|
onProgress: ({ processedBytes, totalBytes, percent }) => {
|
|
127
155
|
console.log(`Sending: ${percent.toFixed(1)}%`);
|
|
128
156
|
},
|
|
129
157
|
onComplete: () => console.log('Transfer complete!'),
|
|
130
158
|
onError: (err) => console.error('Error:', err),
|
|
159
|
+
onCancel: ({ cancelledBy }) => console.log(`Cancelled by ${cancelledBy}`),
|
|
160
|
+
onDisconnect: () => console.log('Receiver disconnected'),
|
|
131
161
|
});
|
|
132
162
|
|
|
133
|
-
//
|
|
134
|
-
|
|
163
|
+
// Session control
|
|
164
|
+
console.log('Status:', session.getStatus());
|
|
165
|
+
console.log('Bytes sent:', session.getBytesSent());
|
|
166
|
+
session.stop(); // Cancel
|
|
135
167
|
```
|
|
136
168
|
|
|
137
|
-
###
|
|
169
|
+
### P2P File Transfer (Receiver)
|
|
138
170
|
|
|
139
171
|
```javascript
|
|
140
|
-
import { startP2PReceive } from '@dropgate/core';
|
|
141
|
-
|
|
142
172
|
const Peer = await loadPeerJS();
|
|
143
173
|
|
|
144
|
-
const session = await
|
|
174
|
+
const session = await client.p2pReceive({
|
|
145
175
|
code: 'ABCD-1234',
|
|
146
176
|
Peer,
|
|
147
|
-
|
|
148
|
-
port: 443,
|
|
149
|
-
secure: true,
|
|
150
|
-
onMeta: ({ name, total }) => {
|
|
177
|
+
onMeta: ({ name, total, fileCount, files }) => {
|
|
151
178
|
console.log(`Receiving: ${name} (${total} bytes)`);
|
|
179
|
+
if (fileCount) console.log(`Multi-file transfer: ${fileCount} files`);
|
|
152
180
|
},
|
|
153
181
|
onData: async (chunk) => {
|
|
154
|
-
// Consumer handles file writing (e.g., streamSaver, fs.write)
|
|
155
182
|
await writer.write(chunk);
|
|
156
183
|
},
|
|
157
184
|
onProgress: ({ processedBytes, totalBytes, percent }) => {
|
|
158
185
|
console.log(`Receiving: ${percent.toFixed(1)}%`);
|
|
159
186
|
},
|
|
160
|
-
|
|
187
|
+
// Multi-file transfers: called when each individual file starts/ends
|
|
188
|
+
onFileStart: ({ fileIndex, name, size }) => {
|
|
189
|
+
console.log(`File ${fileIndex}: ${name} (${size} bytes)`);
|
|
190
|
+
},
|
|
191
|
+
onFileEnd: ({ fileIndex, receivedBytes }) => {
|
|
192
|
+
console.log(`File ${fileIndex} complete (${receivedBytes} bytes)`);
|
|
193
|
+
},
|
|
194
|
+
onComplete: ({ received, total }) => console.log(`Complete! ${received}/${total}`),
|
|
195
|
+
onCancel: ({ cancelledBy }) => console.log(`Cancelled by ${cancelledBy}`),
|
|
196
|
+
onError: (err) => console.error('Error:', err),
|
|
197
|
+
onDisconnect: () => console.log('Sender disconnected'),
|
|
161
198
|
});
|
|
199
|
+
|
|
200
|
+
session.stop(); // Cancel
|
|
162
201
|
```
|
|
163
202
|
|
|
164
|
-
###
|
|
203
|
+
### P2P with File Preview (Receiver)
|
|
165
204
|
|
|
166
205
|
Use `autoReady: false` to show a file preview before starting the transfer:
|
|
167
206
|
|
|
168
207
|
```javascript
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const Peer = await loadPeerJS();
|
|
172
|
-
let writer;
|
|
173
|
-
|
|
174
|
-
const session = await startP2PReceive({
|
|
208
|
+
const session = await client.p2pReceive({
|
|
175
209
|
code: 'ABCD-1234',
|
|
176
210
|
Peer,
|
|
177
|
-
|
|
178
|
-
secure: true,
|
|
179
|
-
autoReady: false, // Don't start transfer automatically
|
|
211
|
+
autoReady: false,
|
|
180
212
|
onMeta: ({ name, total, sendReady }) => {
|
|
181
|
-
// Show file preview to user
|
|
182
213
|
console.log(`File: ${name} (${total} bytes)`);
|
|
183
214
|
showPreviewUI(name, total);
|
|
184
215
|
|
|
185
|
-
// When user confirms, create writer and start transfer
|
|
186
216
|
confirmButton.onclick = () => {
|
|
187
217
|
writer = createWriteStream(name);
|
|
188
218
|
sendReady(); // Signal sender to begin transfer
|
|
@@ -198,93 +228,182 @@ const session = await startP2PReceive({
|
|
|
198
228
|
});
|
|
199
229
|
```
|
|
200
230
|
|
|
201
|
-
###
|
|
231
|
+
### Standalone Server Info
|
|
202
232
|
|
|
203
|
-
|
|
204
|
-
import { DropgateClient } from '@dropgate/core';
|
|
233
|
+
For one-off checks before constructing a client:
|
|
205
234
|
|
|
206
|
-
|
|
235
|
+
```javascript
|
|
236
|
+
import { getServerInfo } from '@dropgate/core';
|
|
207
237
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
port: 443,
|
|
212
|
-
secure: true,
|
|
213
|
-
fileId: 'abc123',
|
|
214
|
-
keyB64: 'base64-key-from-url-hash', // Required for encrypted files
|
|
215
|
-
onProgress: ({ phase, percent, processedBytes, totalBytes }) => {
|
|
216
|
-
console.log(`${phase}: ${percent}% (${processedBytes}/${totalBytes})`);
|
|
217
|
-
},
|
|
218
|
-
onData: async (chunk) => {
|
|
219
|
-
// Consumer handles file writing (e.g., fs.write, streamSaver)
|
|
220
|
-
await writer.write(chunk);
|
|
221
|
-
},
|
|
238
|
+
const { serverInfo } = await getServerInfo({
|
|
239
|
+
server: 'https://dropgate.link',
|
|
240
|
+
timeoutMs: 5000,
|
|
222
241
|
});
|
|
223
242
|
|
|
224
|
-
console.log('
|
|
243
|
+
console.log('Server version:', serverInfo.version);
|
|
244
|
+
```
|
|
225
245
|
|
|
226
|
-
|
|
227
|
-
const memoryResult = await client.downloadFile({
|
|
228
|
-
host: 'dropgate.link',
|
|
229
|
-
secure: true,
|
|
230
|
-
fileId: 'abc123',
|
|
231
|
-
});
|
|
246
|
+
## Metadata Fetching
|
|
232
247
|
|
|
233
|
-
|
|
234
|
-
|
|
248
|
+
The core library provides intelligent metadata fetching methods that handle all the complexity of deriving computed fields from server responses.
|
|
249
|
+
|
|
250
|
+
### Philosophy
|
|
251
|
+
|
|
252
|
+
The server stores and sends only **minimal, essential data**:
|
|
253
|
+
- For files: Basic metadata (size, encryption flag, filename)
|
|
254
|
+
- For bundles: File list (for unsealed) or encrypted manifest (for sealed)
|
|
255
|
+
|
|
256
|
+
The core library **derives all computed fields**:
|
|
257
|
+
- `totalSizeBytes`: Sum of all file sizes
|
|
258
|
+
- `fileCount`: Length of files array
|
|
259
|
+
- Decrypted manifest contents (for sealed bundles)
|
|
260
|
+
|
|
261
|
+
### Benefits
|
|
262
|
+
|
|
263
|
+
1. **Single Source of Truth**: All derivation logic lives in one place (the core library)
|
|
264
|
+
2. **Server Efficiency**: Server stores less redundant data
|
|
265
|
+
3. **Client Flexibility**: Clients can compute fields in any format they need
|
|
266
|
+
4. **Future-Proof**: Changes to derivation logic only require library updates
|
|
267
|
+
|
|
268
|
+
### Usage
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// The core library automatically:
|
|
272
|
+
// 1. Fetches raw metadata from the server
|
|
273
|
+
// 2. Decrypts sealed bundle manifests (if keyB64 provided)
|
|
274
|
+
// 3. Derives totalSizeBytes and fileCount from files array
|
|
275
|
+
// 4. Returns a complete BundleMetadata object
|
|
276
|
+
|
|
277
|
+
const meta = await client.getBundleMetadata('bundle-id', 'optional-key');
|
|
278
|
+
// meta.totalSizeBytes and meta.fileCount are computed client-side
|
|
235
279
|
```
|
|
236
280
|
|
|
237
|
-
##
|
|
281
|
+
## API Reference
|
|
238
282
|
|
|
239
|
-
###
|
|
283
|
+
### DropgateClient
|
|
240
284
|
|
|
241
285
|
The main client class for interacting with Dropgate servers.
|
|
242
286
|
|
|
243
|
-
####
|
|
287
|
+
#### Constructor Options
|
|
244
288
|
|
|
245
289
|
| Option | Type | Required | Description |
|
|
246
290
|
| --- | --- | --- | --- |
|
|
247
291
|
| `clientVersion` | `string` | Yes | Client version for compatibility checking |
|
|
248
|
-
| `
|
|
292
|
+
| `server` | `string \| ServerTarget` | Yes | Server URL or `{ host, port?, secure? }` |
|
|
293
|
+
| `fallbackToHttp` | `boolean` | No | Auto-retry with HTTP if HTTPS fails in `connect()` |
|
|
294
|
+
| `chunkSize` | `number` | No | Upload chunk size fallback (default: 5MB). The server's configured chunk size (from `/api/info`) takes precedence when available. |
|
|
249
295
|
| `fetchFn` | `FetchFn` | No | Custom fetch implementation |
|
|
250
296
|
| `cryptoObj` | `CryptoAdapter` | No | Custom crypto implementation |
|
|
251
297
|
| `base64` | `Base64Adapter` | No | Custom base64 encoder/decoder |
|
|
252
|
-
| `logger` | `LoggerFn` | No | Custom logger function |
|
|
253
298
|
|
|
254
|
-
####
|
|
299
|
+
#### Properties
|
|
300
|
+
|
|
301
|
+
| Property | Type | Description |
|
|
302
|
+
| --- | --- | --- |
|
|
303
|
+
| `baseUrl` | `string` | Resolved server base URL (may change if HTTP fallback occurs) |
|
|
304
|
+
| `serverTarget` | `ServerTarget` | Derived `{ host, port, secure }` from `baseUrl` |
|
|
305
|
+
|
|
306
|
+
#### Methods
|
|
255
307
|
|
|
256
308
|
| Method | Description |
|
|
257
309
|
| --- | --- |
|
|
258
|
-
| `
|
|
259
|
-
| `
|
|
260
|
-
| `
|
|
310
|
+
| `connect(opts?)` | Fetch server info, check compatibility, cache result |
|
|
311
|
+
| `getFileMetadata(fileId, opts?)` | Fetch metadata for a single file |
|
|
312
|
+
| `getBundleMetadata(bundleId, keyB64?, opts?)` | Fetch bundle metadata with automatic manifest decryption and field derivation |
|
|
313
|
+
| `uploadFiles(opts)` | Upload a file with optional encryption |
|
|
314
|
+
| `downloadFiles(opts)` | Download a file with optional decryption |
|
|
315
|
+
| `p2pSend(opts)` | Start a P2P send session |
|
|
316
|
+
| `p2pReceive(opts)` | Start a P2P receive session |
|
|
261
317
|
| `validateUploadInputs(opts)` | Validate file and settings before upload |
|
|
262
|
-
| `resolveShareTarget(value, opts)` | Resolve a sharing code via the server |
|
|
318
|
+
| `resolveShareTarget(value, opts?)` | Resolve a sharing code via the server |
|
|
263
319
|
|
|
264
|
-
###
|
|
320
|
+
### P2P Utility Functions
|
|
265
321
|
|
|
266
322
|
| Function | Description |
|
|
267
323
|
| --- | --- |
|
|
268
|
-
| `startP2PSend(opts)` | Start a P2P send session |
|
|
269
|
-
| `startP2PReceive(opts)` | Start a P2P receive session |
|
|
270
324
|
| `generateP2PCode(cryptoObj?)` | Generate a secure sharing code |
|
|
271
325
|
| `isP2PCodeLike(code)` | Check if a string looks like a P2P code |
|
|
272
326
|
| `isSecureContextForP2P(hostname, isSecureContext)` | Check if P2P is allowed |
|
|
273
327
|
| `isLocalhostHostname(hostname)` | Check if hostname is localhost |
|
|
274
328
|
|
|
275
|
-
###
|
|
329
|
+
### Utility Functions
|
|
276
330
|
|
|
277
331
|
| Function | Description |
|
|
278
332
|
| --- | --- |
|
|
279
|
-
| `getServerInfo(opts)` | Fetch server info and capabilities |
|
|
280
|
-
| `parseServerUrl(urlStr)` | Parse a URL string into host/port/secure |
|
|
281
|
-
| `buildBaseUrl(opts)` | Build a URL from host/port/secure |
|
|
333
|
+
| `getServerInfo(opts)` | Fetch server info and capabilities (standalone) |
|
|
282
334
|
| `lifetimeToMs(value, unit)` | Convert lifetime to milliseconds |
|
|
283
335
|
| `estimateTotalUploadSizeBytes(...)` | Estimate upload size with encryption overhead |
|
|
284
336
|
| `bytesToBase64(bytes)` | Convert bytes to base64 |
|
|
337
|
+
| `arrayBufferToBase64(buffer)` | Convert an ArrayBuffer to base64 |
|
|
285
338
|
| `base64ToBytes(b64)` | Convert base64 to bytes |
|
|
339
|
+
| `parseSemverMajorMinor(version)` | Parse a semver string into `{ major, minor }` |
|
|
340
|
+
| `validatePlainFilename(name)` | Validate that a filename has no path traversal or illegal characters |
|
|
286
341
|
|
|
287
|
-
###
|
|
342
|
+
### Crypto Functions
|
|
343
|
+
|
|
344
|
+
| Function | Description |
|
|
345
|
+
| --- | --- |
|
|
346
|
+
| `sha256Hex(data)` | Compute a SHA-256 hex digest |
|
|
347
|
+
| `generateAesGcmKey()` | Generate a random AES-256-GCM CryptoKey |
|
|
348
|
+
| `exportKeyBase64(key)` | Export a CryptoKey as a base64 string |
|
|
349
|
+
| `importKeyFromBase64(b64)` | Import a CryptoKey from a base64 string |
|
|
350
|
+
| `encryptToBlob(blob, key)` | Encrypt a Blob with AES-256-GCM |
|
|
351
|
+
| `encryptFilenameToBase64(name, key)` | Encrypt a filename string to base64 |
|
|
352
|
+
| `decryptChunk(chunk, key)` | Decrypt an AES-256-GCM encrypted chunk |
|
|
353
|
+
| `decryptFilenameFromBase64(b64, key)` | Decrypt a filename from base64 |
|
|
354
|
+
|
|
355
|
+
### Adapter Defaults
|
|
356
|
+
|
|
357
|
+
| Function | Description |
|
|
358
|
+
| --- | --- |
|
|
359
|
+
| `getDefaultFetch()` | Get the default `fetch` implementation for the current environment |
|
|
360
|
+
| `getDefaultCrypto()` | Get the default `CryptoAdapter` (Web Crypto API) |
|
|
361
|
+
| `getDefaultBase64()` | Get the default `Base64Adapter` for the current environment |
|
|
362
|
+
|
|
363
|
+
### Network Helpers (advanced)
|
|
364
|
+
|
|
365
|
+
| Function | Description |
|
|
366
|
+
| --- | --- |
|
|
367
|
+
| `buildBaseUrl(server)` | Build a base URL string from a server URL or `ServerTarget` |
|
|
368
|
+
| `parseServerUrl(url)` | Parse a URL string into a `ServerTarget` |
|
|
369
|
+
| `fetchJson(url, opts?)` | Fetch JSON with timeout and error handling |
|
|
370
|
+
| `sleep(ms)` | Promise-based delay |
|
|
371
|
+
| `makeAbortSignal(timeoutMs?)` | Create an `AbortSignal` with optional timeout |
|
|
372
|
+
|
|
373
|
+
### Constants
|
|
374
|
+
|
|
375
|
+
| Constant | Description |
|
|
376
|
+
| --- | --- |
|
|
377
|
+
| `DEFAULT_CHUNK_SIZE` | Default upload chunk size in bytes (5 MB) |
|
|
378
|
+
| `AES_GCM_IV_BYTES` | AES-GCM initialisation vector length |
|
|
379
|
+
| `AES_GCM_TAG_BYTES` | AES-GCM authentication tag length |
|
|
380
|
+
| `ENCRYPTION_OVERHEAD_PER_CHUNK` | Total encryption overhead added to each chunk |
|
|
381
|
+
|
|
382
|
+
### StreamingZipWriter
|
|
383
|
+
|
|
384
|
+
A streaming ZIP assembler for multi-file P2P transfers. Wraps [fflate](https://github.com/101arrowz/fflate) and produces a valid ZIP archive without buffering entire files in memory.
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
import { StreamingZipWriter } from '@dropgate/core';
|
|
388
|
+
|
|
389
|
+
const zipWriter = new StreamingZipWriter((zipChunk) => {
|
|
390
|
+
// Write each ZIP chunk to your output (e.g., StreamSaver writer)
|
|
391
|
+
writer.write(zipChunk);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
zipWriter.startFile('photo.jpg');
|
|
395
|
+
zipWriter.writeChunk(chunk1);
|
|
396
|
+
zipWriter.writeChunk(chunk2);
|
|
397
|
+
zipWriter.endFile();
|
|
398
|
+
|
|
399
|
+
zipWriter.startFile('notes.txt');
|
|
400
|
+
zipWriter.writeChunk(chunk3);
|
|
401
|
+
zipWriter.endFile();
|
|
402
|
+
|
|
403
|
+
zipWriter.finalize(); // Flush remaining data and write ZIP footer
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Error Classes
|
|
288
407
|
|
|
289
408
|
| Class | Description |
|
|
290
409
|
| --- | --- |
|
|
@@ -295,14 +414,15 @@ The main client class for interacting with Dropgate servers.
|
|
|
295
414
|
| `DropgateAbortError` | Operation aborted |
|
|
296
415
|
| `DropgateTimeoutError` | Operation timed out |
|
|
297
416
|
|
|
298
|
-
##
|
|
417
|
+
## Browser Usage
|
|
299
418
|
|
|
300
419
|
For browser environments, you can use the IIFE bundle:
|
|
301
420
|
|
|
302
421
|
```html
|
|
303
422
|
<script src="/path/to/dropgate-core.browser.js"></script>
|
|
304
423
|
<script>
|
|
305
|
-
const { DropgateClient
|
|
424
|
+
const { DropgateClient } = DropgateCore;
|
|
425
|
+
const client = new DropgateClient({ clientVersion: '3.0.0', server: location.origin });
|
|
306
426
|
// ...
|
|
307
427
|
</script>
|
|
308
428
|
```
|
|
@@ -311,33 +431,44 @@ Or as an ES module:
|
|
|
311
431
|
|
|
312
432
|
```html
|
|
313
433
|
<script type="module">
|
|
314
|
-
import { DropgateClient
|
|
434
|
+
import { DropgateClient } from '/path/to/dropgate-core.js';
|
|
435
|
+
const client = new DropgateClient({ clientVersion: '3.0.0', server: location.origin });
|
|
315
436
|
// ...
|
|
316
437
|
</script>
|
|
317
438
|
```
|
|
318
439
|
|
|
319
|
-
##
|
|
440
|
+
## P2P Consumer Responsibilities
|
|
320
441
|
|
|
321
|
-
The P2P
|
|
442
|
+
The P2P methods are **headless**. The consumer is responsible for:
|
|
322
443
|
|
|
323
|
-
1. **Loading PeerJS**: Provide the `Peer` constructor to
|
|
444
|
+
1. **Loading PeerJS**: Provide the `Peer` constructor to `p2pSend`/`p2pReceive`
|
|
324
445
|
2. **File Writing**: Handle received chunks via `onData` callback (e.g., using streamSaver)
|
|
325
446
|
3. **UI Updates**: React to callbacks (`onProgress`, `onStatus`, etc.)
|
|
326
447
|
|
|
327
448
|
This design allows the library to work in any environment (browser, Electron, Node.js with WebRTC).
|
|
328
449
|
|
|
329
|
-
|
|
450
|
+
### Large File Support
|
|
451
|
+
|
|
452
|
+
The P2P implementation is designed for **unlimited file sizes** with constant memory usage:
|
|
453
|
+
|
|
454
|
+
- **Stream-through architecture**: Chunks flow immediately to `onData`, no buffering
|
|
455
|
+
- **Flow control**: Sender pauses when receiver's write queue backs up
|
|
456
|
+
- **WebRTC reliability**: SCTP provides reliable, ordered, checksum-verified delivery
|
|
457
|
+
|
|
458
|
+
> **Note**: For large files, always use the `onData` callback approach rather than buffering in memory.
|
|
459
|
+
|
|
460
|
+
## License
|
|
330
461
|
|
|
331
462
|
Licensed under the **Apache-2.0 License**.
|
|
332
463
|
See the [LICENSE](./LICENSE) file for details.
|
|
333
464
|
|
|
334
|
-
##
|
|
465
|
+
## Acknowledgements
|
|
335
466
|
|
|
336
467
|
* Logo designed by [TheFuturisticIdiot](https://youtube.com/TheFuturisticIdiot)
|
|
337
468
|
* Built with [TypeScript](https://www.typescriptlang.org/)
|
|
338
469
|
* Inspired by the growing need for privacy-respecting, open file transfer tools
|
|
339
470
|
|
|
340
|
-
##
|
|
471
|
+
## Contact Us
|
|
341
472
|
|
|
342
473
|
* **Need help or want to chat?** [Join our Discord Server](https://diamonddigital.dev/discord)
|
|
343
474
|
* **Found a bug?** [Open an issue](https://github.com/WillTDA/Dropgate/issues)
|