libfw-client 0.3.2 → 0.4.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 CHANGED
@@ -16,7 +16,13 @@ const client = new LibfwClient({
16
16
  downloadWindow: 4, // parallel byte-range GETs per single file download
17
17
  // (raise to reduce download stutter on high-latency links)
18
18
  compress: true, // zrip per-block compression
19
- onEvent: (e) => console.log(e), // { type: 'progress', done, total }
19
+ autoTune: true, // adaptive tuning: probes /capabilities and ramps
20
+ // concurrency/windows/chunk sizes from real stats
21
+ onEvent: (e) => {
22
+ if (e.type === 'progress') updateProgressBar(e.done, e.total);
23
+ else if (e.type === 'tuning') renderTuning(e.phase, e.params, e.stats);
24
+ // other types: fileStart, fileCompleted, ...
25
+ },
20
26
  });
21
27
 
22
28
  // Download a whole folder. Uses showDirectoryPicker when the File System
@@ -108,12 +114,28 @@ dist/libfw-client.umd.js UMD bundle (after build:umd)
108
114
  for the in-memory `'browser'` fallback. File sizes are pre-checked
109
115
  against it before buffering; a download that would exceed it rejects
110
116
  with a `too-large` `LibfwError` instead of risking an OOM. `0` disables.
117
+ - `autoTune: boolean` (default `false`) — enable the adaptive tuning
118
+ engine. The engine probes the server's `/capabilities` limits and
119
+ TCP-style ramps concurrency / windows / chunk sizes (and the zrip
120
+ level) from the advertised minimums using real transfer stats. When
121
+ disabled, the configured static values are used as-is.
122
+ - `tuneTtlMs: number` (default `3600000`, 1 h) — how long a settled
123
+ tuning result is reused for the same server origin before re-ramping.
111
124
  - `downloadFolder(token, dirPath?) → Promise<number>`
112
125
  - `downloadFile(token, filePath) → Promise<number>`
113
126
  - `upload(token, files?) → Promise<number>`
114
127
  - `clearResumeStore(direction?) → Promise<number>`
115
128
  - `pause()`, `resume()`, `cancel()`
116
129
  - `state()`, `progress()`, `doneBytes()`, `totalBytes()`
130
+ - `tuneStatus() → { phase, params, stats, capsHash } | null` — live
131
+ adaptive-tuning status. `phase` is `uninitialized | ramping | settled |
132
+ degraded`; `params` is `{ concurrency, uploadWindow, downloadWindow,
133
+ chunkSize, downloadChunkSize, compressLevel }`; `stats` is
134
+ `{ rttMs, mbps }` (EWMA request RTT, last-window throughput). `null`
135
+ until the WASM engine is initialised.
136
+ - Events: with `autoTune` enabled, `onEvent` additionally receives
137
+ `{ type: 'tuning', phase, params, stats }` on every phase transition /
138
+ window evaluation.
117
139
  - Errors: every rejection is a `LibfwError` with a stable `code`.
118
140
 
119
141
  See `index.d.ts` for the full type surface.
package/index.d.ts CHANGED
@@ -36,6 +36,40 @@ export interface UploadEntry {
36
36
  mtime: number;
37
37
  }
38
38
 
39
+ /** Adaptive-tuning parameters the engine is currently tuned to. */
40
+ export interface TuningParams {
41
+ /** Cross-file transfer concurrency. */
42
+ concurrency: number;
43
+ /** In-flight chunks per single-file upload. */
44
+ uploadWindow: number;
45
+ /** In-flight byte-range GETs per single-file download. */
46
+ downloadWindow: number;
47
+ /** Upload chunk size in bytes. */
48
+ chunkSize: number;
49
+ /** Download byte-range size in bytes. */
50
+ downloadChunkSize: number;
51
+ /** zrip compression level (negative = faster, positive = smaller). */
52
+ compressLevel: number;
53
+ }
54
+
55
+ /** Last-window transfer statistics reported by the tuning engine. */
56
+ export interface TuningStats {
57
+ /** EWMA request round-trip time in milliseconds. */
58
+ rttMs: number;
59
+ /** Last-window throughput in megabits per second. */
60
+ mbps: number;
61
+ }
62
+
63
+ /** Live adaptive-tuning status (see {@link LibfwClient.tuneStatus}). */
64
+ export interface TuneStatus {
65
+ /** `uninitialized` until the first measurement window completes. */
66
+ phase: 'uninitialized' | 'ramping' | 'settled' | 'degraded';
67
+ params: TuningParams;
68
+ stats: TuningStats;
69
+ /** Hash of the server `/capabilities` payload the tuning is based on. */
70
+ capsHash: string;
71
+ }
72
+
39
73
  /** Progress / lifecycle event delivered via `options.onEvent`. */
40
74
  export interface LibfwEvent {
41
75
  /** `fileStart`, `fileCompleted`, `progress`. */
@@ -48,6 +82,14 @@ export interface LibfwEvent {
48
82
  total?: number;
49
83
  }
50
84
 
85
+ /** Tuning event delivered via `options.onEvent` when `autoTune` is enabled. */
86
+ export interface LibfwTuningEvent {
87
+ type: 'tuning';
88
+ phase: TuneStatus['phase'];
89
+ params: TuningParams;
90
+ stats: TuningStats;
91
+ }
92
+
51
93
  /** Options accepted by the {@link LibfwClient} constructor. */
52
94
  export interface LibfwClientOptions {
53
95
  /**
@@ -114,8 +156,21 @@ export interface LibfwClientOptions {
114
156
  * limit. Default `536870912` (512 MiB).
115
157
  */
116
158
  maxFallbackBytes?: number;
117
- /** Optional progress/state listener. */
118
- onEvent?: (event: LibfwEvent) => void;
159
+ /**
160
+ * Enable the adaptive tuning engine: the engine probes the server's
161
+ * `/capabilities` limits and TCP-style ramps concurrency / windows /
162
+ * chunk sizes (and the zrip level) from the advertised minimums using
163
+ * real transfer stats. When disabled the configured static values are
164
+ * used as-is. Default `false`.
165
+ */
166
+ autoTune?: boolean;
167
+ /**
168
+ * How long (ms) a settled tuning result is reused for the same server
169
+ * origin before re-ramping. Default `3600000` (1 hour).
170
+ */
171
+ tuneTtlMs?: number;
172
+ /** Optional progress/state listener. Tuning updates arrive as `{ type: 'tuning', phase, params, stats }`. */
173
+ onEvent?: (event: LibfwEvent | LibfwTuningEvent) => void;
119
174
  }
120
175
 
121
176
  /**
@@ -192,6 +247,19 @@ export declare class LibfwClient {
192
247
  /** Total bytes to transfer. */
193
248
  totalBytes(): number;
194
249
 
250
+ /**
251
+ * Live adaptive-tuning status.
252
+ *
253
+ * @returns `{ phase, params, stats, capsHash }` — `phase` is
254
+ * `uninitialized | ramping | settled | degraded`; `params` holds the
255
+ * tuned `concurrency` / `uploadWindow` / `downloadWindow` / `chunkSize`
256
+ * / `downloadChunkSize` / `compressLevel`; `stats` is
257
+ * `{ rttMs, mbps }` (EWMA request RTT, last-window throughput).
258
+ * `null` until the WASM engine is initialised (or when `autoTune` is
259
+ * disabled, `phase` stays `uninitialized`).
260
+ */
261
+ tuneStatus(): TuneStatus | null;
262
+
195
263
  /**
196
264
  * Delete persisted resume state (IndexedDB).
197
265
  *
package/index.js CHANGED
@@ -235,8 +235,16 @@ export class LibfwClient {
235
235
  * before any bytes are buffered; a download that would exceed it is
236
236
  * rejected with a `too-large` error instead of risking an OOM.
237
237
  * `0` disables the limit.
238
+ * @param {boolean} [options.autoTune=false] enable the adaptive tuning
239
+ * engine: the engine probes the server's `/capabilities` limits and
240
+ * TCP-style ramps concurrency / windows / chunk sizes (and the zrip
241
+ * level) from the advertised minimums using real transfer stats.
242
+ * When disabled the configured static values are used as-is.
243
+ * @param {number} [options.tuneTtlMs=3600000] how long a settled tuning
244
+ * result is reused for the same server origin before re-ramping
238
245
  * @param {(event: {type: string, done: number, total: number, path?: string, error?: string}) => void} [options.onEvent]
239
- * optional progress/state listener
246
+ * optional progress/state listener. Tuning updates arrive as
247
+ * `{ type: 'tuning', phase, params, stats }` events.
240
248
  */
241
249
  constructor(options = {}) {
242
250
  this._options = {
@@ -254,6 +262,8 @@ export class LibfwClient {
254
262
  wasmUrl: null,
255
263
  downloadMode: 'auto',
256
264
  maxFallbackBytes: 512 * 1024 * 1024,
265
+ autoTune: false,
266
+ tuneTtlMs: 3600000,
257
267
  onEvent: null,
258
268
  ...options,
259
269
  };
@@ -310,8 +320,15 @@ export class LibfwClient {
310
320
  baseRetryDelayMs: this._options.baseRetryDelayMs,
311
321
  maxRetryDelayMs: this._options.maxRetryDelayMs,
312
322
  timeoutMs: this._options.timeoutMs,
323
+ autoTune: this._options.autoTune,
324
+ tuneTtlMs: this._options.tuneTtlMs,
313
325
  });
314
326
  engine.set_callbacks(this._makeCallbacks());
327
+ // Forward tuning state changes (phase transitions, window evaluations)
328
+ // to the SDK consumer as `{ type: 'tuning', phase, params, stats }`.
329
+ engine.set_tune_callback((phase, params, stats) => {
330
+ this._emit({ type: 'tuning', phase, params, stats });
331
+ });
315
332
  this._engine = engine;
316
333
  return engine;
317
334
  }
@@ -938,6 +955,20 @@ export class LibfwClient {
938
955
  * @throws {LibfwError}
939
956
  */
940
957
  async upload(token, files) {
958
+ // Snapshot the FileList SYNCHRONOUSLY, before any await: `input.files`
959
+ // is a LIVE list that the page typically clears (`input.value = ''`)
960
+ // right after the change event — while we await WASM init below, that
961
+ // clear would empty a captured FileList to zero entries and the upload
962
+ // would silently transfer 0 bytes. Copying the File objects now keeps
963
+ // them valid regardless of what the page does to the input afterwards.
964
+ if (
965
+ files !== undefined &&
966
+ files !== null &&
967
+ !Array.isArray(files) &&
968
+ typeof files[Symbol.iterator] === 'function'
969
+ ) {
970
+ files = Array.from(files);
971
+ }
941
972
  const engine = await this._ready();
942
973
  this._uploadFiles.clear();
943
974
  this._uploadPlan = [];
@@ -1087,6 +1118,23 @@ export class LibfwClient {
1087
1118
  return this._engine ? this._engine.total_bytes() : 0;
1088
1119
  }
1089
1120
 
1121
+ /**
1122
+ * Live adaptive-tuning status: `{ phase, params, stats, capsHash }`.
1123
+ *
1124
+ * - `phase`: `uninitialized | ramping | settled | degraded`
1125
+ * - `params`: `{ concurrency, uploadWindow, downloadWindow, chunkSize,
1126
+ * downloadChunkSize, compressLevel }` — the parameters the engine is
1127
+ * currently tuned to
1128
+ * - `stats`: `{ rttMs, mbps }` — EWMA request RTT and last-window
1129
+ * throughput of the most recent transfer
1130
+ *
1131
+ * `null` until the WASM engine is initialised.
1132
+ * @returns {object|null}
1133
+ */
1134
+ tuneStatus() {
1135
+ return this._engine ? this._engine.tune_state() : null;
1136
+ }
1137
+
1090
1138
  // ------------------------------------------------------------- resume store
1091
1139
 
1092
1140
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libfw-client",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "High-performance streaming file & folder transfer SDK for the browser (libfw WASM engine + File System Access API + IndexedDB resume).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,8 +34,8 @@ export class LibfwClient {
34
34
  /**
35
35
  * Create an engine. `options` may include:
36
36
  * `{ concurrency, uploadWindow, downloadWindow, downloadChunkSize,
37
- * compress, chunkSize, maxRetries, baseRetryDelayMs, maxRetryDelayMs,
38
- * timeoutMs }`.
37
+ * compress, compressLevel, chunkSize, maxRetries, baseRetryDelayMs,
38
+ * maxRetryDelayMs, timeoutMs, autoTune, tuneTtlMs }`.
39
39
  */
40
40
  constructor(opts: any);
41
41
  /**
@@ -54,6 +54,11 @@ export class LibfwClient {
54
54
  * Install the JS callbacks object (required before any transfer).
55
55
  */
56
56
  set_callbacks(callbacks: any): void;
57
+ /**
58
+ * Install an `onTuning(phase, params, stats)` callback, invoked on
59
+ * every tuning state change (phase transitions and window evaluations).
60
+ */
61
+ set_tune_callback(cb: any): void;
57
62
  /**
58
63
  * Current state: `idle | downloading | uploading | paused | completed |
59
64
  * failed`.
@@ -63,6 +68,10 @@ export class LibfwClient {
63
68
  * Total bytes to transfer.
64
69
  */
65
70
  total_bytes(): number;
71
+ /**
72
+ * Snapshot the tuning engine: `{ phase, params, stats, capsHash }`.
73
+ */
74
+ tune_state(): any;
66
75
  /**
67
76
  * Upload the files reported by the JS `getFileList` callback.
68
77
  *
@@ -76,6 +85,8 @@ export class LibfwClient {
76
85
  */
77
86
  export function js_option_string(obj: any, key: string): string | undefined;
78
87
 
88
+ export function start(): void;
89
+
79
90
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
80
91
 
81
92
  export interface InitOutput {
@@ -92,19 +103,23 @@ export interface InitOutput {
92
103
  readonly libfwclient_progress: (a: number) => number;
93
104
  readonly libfwclient_resume: (a: number) => void;
94
105
  readonly libfwclient_set_callbacks: (a: number, b: any) => void;
106
+ readonly libfwclient_set_tune_callback: (a: number, b: any) => void;
95
107
  readonly libfwclient_state: (a: number) => [number, number];
96
108
  readonly libfwclient_total_bytes: (a: number) => number;
109
+ readonly libfwclient_tune_state: (a: number) => any;
97
110
  readonly libfwclient_upload: (a: number, b: number, c: number, d: number, e: number) => any;
111
+ readonly start: () => void;
98
112
  readonly wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___wasm_bindgen_1e05ddb24c0b7df4___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_1e05ddb24c0b7df4___JsError___true_: (a: number, b: number, c: any) => [number, number];
99
113
  readonly wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___js_sys_bb6c79d0abe11c10___Function_fn_wasm_bindgen_1e05ddb24c0b7df4___JsValue_____wasm_bindgen_1e05ddb24c0b7df4___sys__Undefined___js_sys_bb6c79d0abe11c10___Function_fn_wasm_bindgen_1e05ddb24c0b7df4___JsValue_____wasm_bindgen_1e05ddb24c0b7df4___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
114
+ readonly wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___web_sys_cda36541fa15086d___features__gen_ProgressEvent__ProgressEvent______true_: (a: number, b: number, c: any) => void;
100
115
  readonly wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke_______true_: (a: number, b: number) => void;
101
116
  readonly __wbindgen_malloc: (a: number, b: number) => number;
102
117
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
103
118
  readonly __wbindgen_exn_store: (a: number) => void;
104
119
  readonly __externref_table_alloc: () => number;
105
120
  readonly __wbindgen_externrefs: WebAssembly.Table;
106
- readonly __wbindgen_destroy_closure: (a: number, b: number) => void;
107
121
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
122
+ readonly __wbindgen_destroy_closure: (a: number, b: number) => void;
108
123
  readonly __externref_table_dealloc: (a: number) => void;
109
124
  readonly __wbindgen_start: () => void;
110
125
  }
@@ -77,8 +77,8 @@ export class LibfwClient {
77
77
  /**
78
78
  * Create an engine. `options` may include:
79
79
  * `{ concurrency, uploadWindow, downloadWindow, downloadChunkSize,
80
- * compress, chunkSize, maxRetries, baseRetryDelayMs, maxRetryDelayMs,
81
- * timeoutMs }`.
80
+ * compress, compressLevel, chunkSize, maxRetries, baseRetryDelayMs,
81
+ * maxRetryDelayMs, timeoutMs, autoTune, tuneTtlMs }`.
82
82
  * @param {any} opts
83
83
  */
84
84
  constructor(opts) {
@@ -114,6 +114,14 @@ export class LibfwClient {
114
114
  set_callbacks(callbacks) {
115
115
  wasm.libfwclient_set_callbacks(this.__wbg_ptr, callbacks);
116
116
  }
117
+ /**
118
+ * Install an `onTuning(phase, params, stats)` callback, invoked on
119
+ * every tuning state change (phase transitions and window evaluations).
120
+ * @param {any} cb
121
+ */
122
+ set_tune_callback(cb) {
123
+ wasm.libfwclient_set_tune_callback(this.__wbg_ptr, cb);
124
+ }
117
125
  /**
118
126
  * Current state: `idle | downloading | uploading | paused | completed |
119
127
  * failed`.
@@ -139,6 +147,14 @@ export class LibfwClient {
139
147
  const ret = wasm.libfwclient_total_bytes(this.__wbg_ptr);
140
148
  return ret;
141
149
  }
150
+ /**
151
+ * Snapshot the tuning engine: `{ phase, params, stats, capsHash }`.
152
+ * @returns {any}
153
+ */
154
+ tune_state() {
155
+ const ret = wasm.libfwclient_tune_state(this.__wbg_ptr);
156
+ return ret;
157
+ }
142
158
  /**
143
159
  * Upload the files reported by the JS `getFileList` callback.
144
160
  *
@@ -175,6 +191,10 @@ export function js_option_string(obj, key) {
175
191
  }
176
192
  return v2;
177
193
  }
194
+
195
+ export function start() {
196
+ wasm.start();
197
+ }
178
198
  function __wbg_get_imports() {
179
199
  const import0 = {
180
200
  __proto__: null,
@@ -242,6 +262,10 @@ function __wbg_get_imports() {
242
262
  const ret = arg0.body;
243
263
  return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
244
264
  },
265
+ __wbg_call_44b7209e1e252e6a: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
266
+ const ret = arg0.call(arg1, arg2, arg3, arg4);
267
+ return ret;
268
+ }, arguments); },
245
269
  __wbg_call_a6e5c5dce5018821: function() { return handleError(function (arg0, arg1, arg2) {
246
270
  const ret = arg0.call(arg1, arg2);
247
271
  return ret;
@@ -253,6 +277,17 @@ function __wbg_get_imports() {
253
277
  const ret = encodeURIComponent(getStringFromWasm0(arg0, arg1));
254
278
  return ret;
255
279
  },
280
+ __wbg_error_a6fa202b58aa1cd3: function(arg0, arg1) {
281
+ let deferred0_0;
282
+ let deferred0_1;
283
+ try {
284
+ deferred0_0 = arg0;
285
+ deferred0_1 = arg1;
286
+ console.error(getStringFromWasm0(arg0, arg1));
287
+ } finally {
288
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
289
+ }
290
+ },
256
291
  __wbg_fetch_6ecc661950e58d49: function(arg0, arg1) {
257
292
  const ret = arg0.fetch(arg1);
258
293
  return ret;
@@ -261,6 +296,13 @@ function __wbg_get_imports() {
261
296
  const ret = Array.from(arg0);
262
297
  return ret;
263
298
  },
299
+ __wbg_getItem_b96269ddc16cf24a: function() { return handleError(function (arg0, arg1, arg2, arg3) {
300
+ const ret = arg1.getItem(getStringFromWasm0(arg2, arg3));
301
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
302
+ var len1 = WASM_VECTOR_LEN;
303
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
304
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
305
+ }, arguments); },
264
306
  __wbg_getReader_7455d080fa48369b: function(arg0) {
265
307
  const ret = arg0.getReader();
266
308
  return ret;
@@ -322,10 +364,22 @@ function __wbg_get_imports() {
322
364
  const ret = arg0.length;
323
365
  return ret;
324
366
  },
367
+ __wbg_loaded_e4436631cb081781: function(arg0) {
368
+ const ret = arg0.loaded;
369
+ return ret;
370
+ },
371
+ __wbg_localStorage_5bf6ce3f8e51412a: function() { return handleError(function (arg0) {
372
+ const ret = arg0.localStorage;
373
+ return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
374
+ }, arguments); },
325
375
  __wbg_new_0d809930cd1354c6: function() { return handleError(function () {
326
376
  const ret = new Headers();
327
377
  return ret;
328
378
  }, arguments); },
379
+ __wbg_new_227d7c05414eb861: function() {
380
+ const ret = new Error();
381
+ return ret;
382
+ },
329
383
  __wbg_new_32b398fb48b6d94a: function() {
330
384
  const ret = new Array();
331
385
  return ret;
@@ -427,6 +481,9 @@ function __wbg_get_imports() {
427
481
  const ret = arg0.readyState;
428
482
  return ret;
429
483
  },
484
+ __wbg_removeItem_78e03a38da96e0ae: function() { return handleError(function (arg0, arg1, arg2) {
485
+ arg0.removeItem(getStringFromWasm0(arg1, arg2));
486
+ }, arguments); },
430
487
  __wbg_resolve_2191a4dfe481c25b: function(arg0) {
431
488
  const ret = Promise.resolve(arg0);
432
489
  return ret;
@@ -438,6 +495,9 @@ function __wbg_get_imports() {
438
495
  const ret = arg0.setInterval(arg1, arg2);
439
496
  return ret;
440
497
  }, arguments); },
498
+ __wbg_setItem_364a11cf21db9039: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
499
+ arg0.setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
500
+ }, arguments); },
441
501
  __wbg_setRequestHeader_fe390ff50d349432: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
442
502
  arg0.setRequestHeader(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
443
503
  }, arguments); },
@@ -477,6 +537,13 @@ function __wbg_get_imports() {
477
537
  __wbg_set_onreadystatechange_14ce44725c7e0789: function(arg0, arg1) {
478
538
  arg0.onreadystatechange = arg1;
479
539
  },
540
+ __wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) {
541
+ const ret = arg1.stack;
542
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
543
+ const len1 = WASM_VECTOR_LEN;
544
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
545
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
546
+ },
480
547
  __wbg_static_accessor_GLOBAL_4ef717fb391d88b7: function() {
481
548
  const ret = typeof global === 'undefined' ? null : global;
482
549
  return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
@@ -509,26 +576,35 @@ function __wbg_get_imports() {
509
576
  const ret = arg0.then(arg1);
510
577
  return ret;
511
578
  },
579
+ __wbg_total_21672ff1bd8d23ea: function(arg0) {
580
+ const ret = arg0.total;
581
+ return ret;
582
+ },
512
583
  __wbg_upload_65cdbdfcc901f1b1: function() { return handleError(function (arg0) {
513
584
  const ret = arg0.upload;
514
585
  return ret;
515
586
  }, arguments); },
516
587
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
517
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 163, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
588
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 198, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
518
589
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___wasm_bindgen_1e05ddb24c0b7df4___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_1e05ddb24c0b7df4___JsError___true_);
519
590
  return ret;
520
591
  },
521
592
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
522
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 5, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
593
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("ProgressEvent")], shim_idx: 5, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
594
+ const ret = makeMutClosure(arg0, arg1, wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___web_sys_cda36541fa15086d___features__gen_ProgressEvent__ProgressEvent______true_);
595
+ return ret;
596
+ },
597
+ __wbindgen_cast_0000000000000003: function(arg0, arg1) {
598
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 7, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
523
599
  const ret = makeMutClosure(arg0, arg1, wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke_______true_);
524
600
  return ret;
525
601
  },
526
- __wbindgen_cast_0000000000000003: function(arg0) {
602
+ __wbindgen_cast_0000000000000004: function(arg0) {
527
603
  // Cast intrinsic for `F64 -> Externref`.
528
604
  const ret = arg0;
529
605
  return ret;
530
606
  },
531
- __wbindgen_cast_0000000000000004: function(arg0, arg1) {
607
+ __wbindgen_cast_0000000000000005: function(arg0, arg1) {
532
608
  // Cast intrinsic for `Ref(String) -> Externref`.
533
609
  const ret = getStringFromWasm0(arg0, arg1);
534
610
  return ret;
@@ -553,6 +629,10 @@ function wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke_______true
553
629
  wasm.wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke_______true_(arg0, arg1);
554
630
  }
555
631
 
632
+ function wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___web_sys_cda36541fa15086d___features__gen_ProgressEvent__ProgressEvent______true_(arg0, arg1, arg2) {
633
+ wasm.wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___web_sys_cda36541fa15086d___features__gen_ProgressEvent__ProgressEvent______true_(arg0, arg1, arg2);
634
+ }
635
+
556
636
  function wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___wasm_bindgen_1e05ddb24c0b7df4___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_1e05ddb24c0b7df4___JsError___true_(arg0, arg1, arg2) {
557
637
  const ret = wasm.wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___wasm_bindgen_1e05ddb24c0b7df4___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_1e05ddb24c0b7df4___JsError___true_(arg0, arg1, arg2);
558
638
  if (ret[1]) {
Binary file
@@ -13,18 +13,22 @@ export const libfwclient_pause: (a: number) => void;
13
13
  export const libfwclient_progress: (a: number) => number;
14
14
  export const libfwclient_resume: (a: number) => void;
15
15
  export const libfwclient_set_callbacks: (a: number, b: any) => void;
16
+ export const libfwclient_set_tune_callback: (a: number, b: any) => void;
16
17
  export const libfwclient_state: (a: number) => [number, number];
17
18
  export const libfwclient_total_bytes: (a: number) => number;
19
+ export const libfwclient_tune_state: (a: number) => any;
18
20
  export const libfwclient_upload: (a: number, b: number, c: number, d: number, e: number) => any;
21
+ export const start: () => void;
19
22
  export const wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___wasm_bindgen_1e05ddb24c0b7df4___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_1e05ddb24c0b7df4___JsError___true_: (a: number, b: number, c: any) => [number, number];
20
23
  export const wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___js_sys_bb6c79d0abe11c10___Function_fn_wasm_bindgen_1e05ddb24c0b7df4___JsValue_____wasm_bindgen_1e05ddb24c0b7df4___sys__Undefined___js_sys_bb6c79d0abe11c10___Function_fn_wasm_bindgen_1e05ddb24c0b7df4___JsValue_____wasm_bindgen_1e05ddb24c0b7df4___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
24
+ export const wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke___web_sys_cda36541fa15086d___features__gen_ProgressEvent__ProgressEvent______true_: (a: number, b: number, c: any) => void;
21
25
  export const wasm_bindgen_1e05ddb24c0b7df4___convert__closures_____invoke_______true_: (a: number, b: number) => void;
22
26
  export const __wbindgen_malloc: (a: number, b: number) => number;
23
27
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
24
28
  export const __wbindgen_exn_store: (a: number) => void;
25
29
  export const __externref_table_alloc: () => number;
26
30
  export const __wbindgen_externrefs: WebAssembly.Table;
27
- export const __wbindgen_destroy_closure: (a: number, b: number) => void;
28
31
  export const __wbindgen_free: (a: number, b: number, c: number) => void;
32
+ export const __wbindgen_destroy_closure: (a: number, b: number) => void;
29
33
  export const __externref_table_dealloc: (a: number) => void;
30
34
  export const __wbindgen_start: () => void;
package/pkg/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "libfw-client",
3
3
  "type": "module",
4
4
  "description": "WASM engine + JS SDK for libfw browser clients",
5
- "version": "0.3.2",
5
+ "version": "0.4.0",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",