@ibm-aspera/sdk 0.19.1 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/commonjs/app/core.d.ts +27 -10
  2. package/dist/commonjs/app/core.js +124 -21
  3. package/dist/commonjs/app/status.d.ts +11 -1
  4. package/dist/commonjs/app/status.js +35 -4
  5. package/dist/commonjs/connect/core.js +3 -0
  6. package/dist/commonjs/helpers/connect-extension.d.ts +8 -0
  7. package/dist/commonjs/helpers/connect-extension.js +58 -0
  8. package/dist/commonjs/helpers/helpers.d.ts +6 -0
  9. package/dist/commonjs/helpers/helpers.js +19 -1
  10. package/dist/commonjs/helpers/ws.d.ts +11 -0
  11. package/dist/commonjs/helpers/ws.js +35 -2
  12. package/dist/commonjs/http-gateway/core.js +12 -13
  13. package/dist/commonjs/http-gateway/download.js +2 -2
  14. package/dist/commonjs/http-gateway/upload.js +2 -2
  15. package/dist/commonjs/http-gateway/v2/app/core.d.ts +84 -0
  16. package/dist/commonjs/http-gateway/v2/app/core.js +170 -0
  17. package/dist/commonjs/http-gateway/v2/app/download.d.ts +15 -0
  18. package/dist/commonjs/http-gateway/v2/app/download.js +68 -0
  19. package/dist/commonjs/http-gateway/v2/app/upload.d.ts +169 -0
  20. package/dist/commonjs/http-gateway/v2/app/upload.js +601 -0
  21. package/dist/commonjs/http-gateway/v2/constants/constants.d.ts +6 -0
  22. package/dist/commonjs/http-gateway/v2/constants/constants.js +9 -0
  23. package/dist/commonjs/http-gateway/v2/constants/messages.d.ts +35 -0
  24. package/dist/commonjs/http-gateway/v2/constants/messages.js +38 -0
  25. package/dist/commonjs/http-gateway/v2/helpers/helpers.d.ts +121 -0
  26. package/dist/commonjs/http-gateway/v2/helpers/helpers.js +294 -0
  27. package/dist/commonjs/http-gateway/v2/helpers/http.d.ts +86 -0
  28. package/dist/commonjs/http-gateway/v2/helpers/http.js +153 -0
  29. package/dist/commonjs/http-gateway/v2/index.d.ts +35 -0
  30. package/dist/commonjs/http-gateway/v2/index.js +70 -0
  31. package/dist/commonjs/http-gateway/v2/models/http-gateway-global.model.d.ts +254 -0
  32. package/dist/commonjs/http-gateway/v2/models/http-gateway-global.model.js +367 -0
  33. package/dist/commonjs/http-gateway/v2/models/models.d.ts +127 -0
  34. package/dist/commonjs/http-gateway/v2/models/models.js +87 -0
  35. package/dist/commonjs/index.d.ts +3 -3
  36. package/dist/commonjs/index.js +3 -1
  37. package/dist/commonjs/models/aspera-sdk.model.d.ts +2 -1
  38. package/dist/commonjs/models/aspera-sdk.model.js +8 -0
  39. package/dist/commonjs/models/models.d.ts +12 -1
  40. package/dist/js/aspera-sdk.js +1 -1
  41. package/dist/js/aspera-sdk.js.LICENSE.txt +1 -1
  42. package/dist/js/aspera-sdk.js.map +1 -1
  43. package/package.json +1 -2
@@ -1,5 +1,5 @@
1
1
  import { AsperaSdkInfo, TransferResponse } from '../models/aspera-sdk.model';
2
- import { CustomBrandingOptions, DataTransferResponse, DropzoneEventData, DropzoneOptions, AsperaSdkSpec, AsperaSdkTransfer, FileDialogOptions, FolderDialogOptions, SaveFileDialogOptions, InitOptions, ModifyTransferOptions, Pagination, PaginatedFilesResponse, ResumeTransferOptions, TransferSpec, ReadChunkAsArrayBufferResponse, ReadAsArrayBufferResponse, SdkCapabilities, SdkStatus, GetChecksumOptions, ChecksumFileResponse, ReadDirectoryOptions, ReadDirectoryResponse, ShowPreferencesPageOptions, TestSshPortsOptions } from '../models/models';
2
+ import { CustomBrandingOptions, DataTransferResponse, DropzoneEventData, DropzoneOptions, AsperaSdkSpec, AsperaSdkTransfer, FileDialogOptions, FolderDialogOptions, SaveFileDialogOptions, InitOptions, ModifyTransferOptions, Pagination, PaginatedFilesResponse, ResumeTransferOptions, TransferSpec, ReadChunkAsArrayBufferResponse, ReadAsArrayBufferResponse, SdkCapabilities, SdkStatus, GetChecksumOptions, ChecksumFileResponse, ReadDirectoryOptions, ReadDirectoryResponse, ShowPreferencesPageOptions, TestSshPortsOptions, TransferClient } from '../models/models';
3
3
  /**
4
4
  * Check if IBM Aspera for Desktop connection works. This function is called by init
5
5
  * when initializing the SDK. This function can be used at any point for checking.
@@ -94,11 +94,7 @@ export declare const init: (options?: InitOptions) => Promise<any>;
94
94
  * @param options - Initialization options. See {@link InitOptions}.
95
95
  *
96
96
  * @example
97
- * // Detect IBM Aspera for desktop (default)
98
- * initSession({ appId: 'my-app' });
99
- *
100
- * @example
101
- * // Detect IBM Aspera for desktop with status handling
97
+ * // Use IBM Aspera for desktop (default)
102
98
  * registerStatusCallback(status => {
103
99
  * if (status === 'RUNNING') {
104
100
  * // Transfer client is ready — enable UI
@@ -118,8 +114,8 @@ export declare const init: (options?: InitOptions) => Promise<any>;
118
114
  * },
119
115
  * });
120
116
  *
121
- * @example
122
- * // Use HTTP Gateway as the sole transport (no desktop app needed)
117
+ * * @example
118
+ * // Use HTTP Gateway only
123
119
  * initSession({
124
120
  * appId: 'my-app',
125
121
  * httpGatewaySettings: {
@@ -128,13 +124,33 @@ export declare const init: (options?: InitOptions) => Promise<any>;
128
124
  * },
129
125
  * });
130
126
  *
127
+ * * @example
128
+ * // Use IBM Aspera for desktop with automatic fallback to IBM Aspera Connect
129
+ * initSession({
130
+ * appId: 'my-app',
131
+ * connectSettings: {
132
+ * fallback: true,
133
+ * },
134
+ * });
135
+ *
131
136
  * @example
132
- * // HTTP Gateway as supplementary transport with Desktop as primary
137
+ * // Use IBM Aspera for desktop with automatic fallback to HTTP Gateway
133
138
  * initSession({
134
139
  * appId: 'my-app',
135
140
  * httpGatewaySettings: {
136
141
  * url: 'https://example.com/aspera/http-gwy',
137
- * forceGateway: false,
142
+ * },
143
+ * });
144
+ *
145
+ * * @example
146
+ * // Use IBM Aspera for desktop or IBM Aspera Connect with automatic fallback to HTTP Gateway
147
+ * initSession({
148
+ * appId: 'my-app',
149
+ * connectSettings: {
150
+ * fallback: true,
151
+ * },
152
+ * httpGatewaySettings: {
153
+ * url: 'https://example.com/aspera/http-gwy',
138
154
  * },
139
155
  * });
140
156
  */
@@ -482,3 +498,4 @@ export declare const getCapabilities: () => SdkCapabilities;
482
498
  * ```
483
499
  */
484
500
  export declare const hasCapability: (capability: keyof SdkCapabilities) => boolean;
501
+ export declare const currentTransferClient: () => TransferClient | undefined;
@@ -11,7 +11,7 @@ var __assign = (this && this.__assign) || function () {
11
11
  return __assign.apply(this, arguments);
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.hasCapability = exports.getCapabilities = exports.readDirectory = exports.getChecksum = exports.readChunkAsArrayBuffer = exports.readAsArrayBuffer = exports.getInfo = exports.removeDropzone = exports.createDropzone = exports.setBranding = exports.modifyTransfer = exports.showDirectory = exports.getFilesList = exports.getTransfer = exports.getAllTransfers = exports.showTransferMonitor = exports.showPreferencesPage = exports.showTransferManager = exports.showPreferences = exports.showAbout = exports.showSaveFileDialog = exports.showSelectFolderDialog = exports.showSelectFileDialog = exports.resumeTransfer = exports.stopTransfer = exports.removeTransfer = exports.deregisterStatusCallback = exports.registerStatusCallback = exports.deregisterActivityCallback = exports.registerActivityCallback = exports.startTransfer = exports.authenticate = exports.testSshPorts = exports.initSession = exports.init = exports.getStatus = exports.initDragDrop = exports.testConnection = void 0;
14
+ exports.currentTransferClient = exports.hasCapability = exports.getCapabilities = exports.readDirectory = exports.getChecksum = exports.readChunkAsArrayBuffer = exports.readAsArrayBuffer = exports.getInfo = exports.removeDropzone = exports.createDropzone = exports.setBranding = exports.modifyTransfer = exports.showDirectory = exports.getFilesList = exports.getTransfer = exports.getAllTransfers = exports.showTransferMonitor = exports.showPreferencesPage = exports.showTransferManager = exports.showPreferences = exports.showAbout = exports.showSaveFileDialog = exports.showSelectFolderDialog = exports.showSelectFileDialog = exports.resumeTransfer = exports.stopTransfer = exports.removeTransfer = exports.deregisterStatusCallback = exports.registerStatusCallback = exports.deregisterActivityCallback = exports.registerActivityCallback = exports.startTransfer = exports.authenticate = exports.testSshPorts = exports.initSession = exports.init = exports.getStatus = exports.initDragDrop = exports.testConnection = void 0;
15
15
  var messages_1 = require("../constants/messages");
16
16
  var client_1 = require("../helpers/client/client");
17
17
  var helpers_1 = require("../helpers/helpers");
@@ -19,7 +19,9 @@ var http_gateway_1 = require("../http-gateway");
19
19
  var core_1 = require("../http-gateway/core");
20
20
  var index_1 = require("../index");
21
21
  var status_1 = require("./status");
22
+ var ws_1 = require("../helpers/ws");
22
23
  var core_2 = require("../connect/core");
24
+ var connect_extension_1 = require("../helpers/connect-extension");
23
25
  /**
24
26
  * Check if IBM Aspera for Desktop connection works. This function is called by init
25
27
  * when initializing the SDK. This function can be used at any point for checking.
@@ -156,6 +158,24 @@ var init = function (options) {
156
158
  throw (0, helpers_1.generateErrorBody)(messages_1.messages.serverError, error);
157
159
  };
158
160
  var getDesktopStartCalls = function () {
161
+ var _a, _b, _c;
162
+ if (((_a = options === null || options === void 0 ? void 0 : options.connectSettings) === null || _a === void 0 ? void 0 : _a.fallback) && !((_b = options === null || options === void 0 ? void 0 : options.connectSettings) === null || _b === void 0 ? void 0 : _b.useConnect)) {
163
+ var timeout_1 = (_c = options === null || options === void 0 ? void 0 : options.retryTimeout) !== null && _c !== void 0 ? _c : 5000;
164
+ return (0, helpers_1.withTimeout)(connectDesktop(), timeout_1)
165
+ .then(function () { return index_1.asperaSdk.globals.sdkResponseData; })
166
+ .catch(function () {
167
+ ws_1.websocketService.disconnect();
168
+ return (0, connect_extension_1.detectConnectExtension)(timeout_1).then(function (found) {
169
+ if (found) {
170
+ return (0, core_2.initConnect)(__assign(__assign({}, options.connectSettings), { hideIncludedInstaller: true }));
171
+ }
172
+ else if (index_1.asperaSdk.httpGatewayIsReady) {
173
+ return index_1.asperaSdk.globals.sdkResponseData;
174
+ }
175
+ throw (0, helpers_1.generateErrorBody)(messages_1.messages.serverError);
176
+ });
177
+ });
178
+ }
159
179
  return connectDesktop()
160
180
  .then(function () { return index_1.asperaSdk.globals.sdkResponseData; })
161
181
  .catch(handleErrors);
@@ -226,11 +246,7 @@ exports.init = init;
226
246
  * @param options - Initialization options. See {@link InitOptions}.
227
247
  *
228
248
  * @example
229
- * // Detect IBM Aspera for desktop (default)
230
- * initSession({ appId: 'my-app' });
231
- *
232
- * @example
233
- * // Detect IBM Aspera for desktop with status handling
249
+ * // Use IBM Aspera for desktop (default)
234
250
  * registerStatusCallback(status => {
235
251
  * if (status === 'RUNNING') {
236
252
  * // Transfer client is ready — enable UI
@@ -250,8 +266,8 @@ exports.init = init;
250
266
  * },
251
267
  * });
252
268
  *
253
- * @example
254
- * // Use HTTP Gateway as the sole transport (no desktop app needed)
269
+ * * @example
270
+ * // Use HTTP Gateway only
255
271
  * initSession({
256
272
  * appId: 'my-app',
257
273
  * httpGatewaySettings: {
@@ -260,23 +276,76 @@ exports.init = init;
260
276
  * },
261
277
  * });
262
278
  *
279
+ * * @example
280
+ * // Use IBM Aspera for desktop with automatic fallback to IBM Aspera Connect
281
+ * initSession({
282
+ * appId: 'my-app',
283
+ * connectSettings: {
284
+ * fallback: true,
285
+ * },
286
+ * });
287
+ *
263
288
  * @example
264
- * // HTTP Gateway as supplementary transport with Desktop as primary
289
+ * // Use IBM Aspera for desktop with automatic fallback to HTTP Gateway
265
290
  * initSession({
266
291
  * appId: 'my-app',
267
292
  * httpGatewaySettings: {
268
293
  * url: 'https://example.com/aspera/http-gwy',
269
- * forceGateway: false,
294
+ * },
295
+ * });
296
+ *
297
+ * * @example
298
+ * // Use IBM Aspera for desktop or IBM Aspera Connect with automatic fallback to HTTP Gateway
299
+ * initSession({
300
+ * appId: 'my-app',
301
+ * connectSettings: {
302
+ * fallback: true,
303
+ * },
304
+ * httpGatewaySettings: {
305
+ * url: 'https://example.com/aspera/http-gwy',
270
306
  * },
271
307
  * });
272
308
  */
273
309
  var initSession = function (options) {
274
- var _a, _b, _c;
310
+ var _a, _b, _c, _d, _e;
275
311
  setupAppId(options);
276
312
  var retryInterval = (_a = options === null || options === void 0 ? void 0 : options.retryInterval) !== null && _a !== void 0 ? _a : 2000;
277
313
  var retryTimeout = (_b = options === null || options === void 0 ? void 0 : options.retryTimeout) !== null && _b !== void 0 ? _b : 5000;
314
+ var hasFallback = ((_c = options === null || options === void 0 ? void 0 : options.connectSettings) === null || _c === void 0 ? void 0 : _c.fallback) && !((_d = options === null || options === void 0 ? void 0 : options.connectSettings) === null || _d === void 0 ? void 0 : _d.useConnect);
278
315
  var startDesktopDetection = function () {
279
- status_1.statusService.startPolling(connectDesktop, retryInterval, retryTimeout);
316
+ var onFallback = hasFallback
317
+ ? function () {
318
+ ws_1.websocketService.disconnect();
319
+ (0, connect_extension_1.detectConnectExtension)(retryTimeout).then(function (found) {
320
+ if (found) {
321
+ (0, core_2.initConnect)(__assign(__assign({}, options.connectSettings), { hideIncludedInstaller: true }));
322
+ var callbackId_1 = status_1.statusService.registerCallback(function (status) {
323
+ if (status === 'INITIALIZING') {
324
+ return;
325
+ }
326
+ status_1.statusService.deregisterCallback(callbackId_1);
327
+ if (status !== 'RUNNING') {
328
+ index_1.asperaSdk.globals.connect.removeEventListener();
329
+ index_1.asperaSdk.globals.connect.stop();
330
+ // Explicitly set status to FAILED since we go back to desktop mode
331
+ status_1.statusService.setStatus('FAILED');
332
+ status_1.statusService.resumePolling(connectDesktop, retryInterval);
333
+ }
334
+ });
335
+ }
336
+ else {
337
+ if (index_1.asperaSdk.httpGatewayIsReady) {
338
+ status_1.statusService.setStatus('DEGRADED');
339
+ }
340
+ else {
341
+ status_1.statusService.setStatus('FAILED');
342
+ }
343
+ status_1.statusService.resumePolling(connectDesktop, retryInterval);
344
+ }
345
+ });
346
+ }
347
+ : undefined;
348
+ status_1.statusService.startPolling(connectDesktop, retryInterval, retryTimeout, onFallback);
280
349
  };
281
350
  var startTransferClient = function () {
282
351
  var _a;
@@ -288,7 +357,7 @@ var initSession = function (options) {
288
357
  }
289
358
  };
290
359
  // HTTP Gateway path
291
- if (((_c = options === null || options === void 0 ? void 0 : options.httpGatewaySettings) === null || _c === void 0 ? void 0 : _c.url) && !index_1.asperaSdk.globals.httpGatewayVerified) {
360
+ if (((_e = options === null || options === void 0 ? void 0 : options.httpGatewaySettings) === null || _e === void 0 ? void 0 : _e.url) && !index_1.asperaSdk.globals.httpGatewayVerified) {
292
361
  status_1.statusService.setStatus('INITIALIZING');
293
362
  (0, http_gateway_1.setupHttpGateway)(options.httpGatewaySettings.url).then(function () {
294
363
  var _a;
@@ -333,9 +402,11 @@ var testSshPorts = function (options) {
333
402
  }
334
403
  var promiseInfo = (0, helpers_1.generatePromiseObjects)();
335
404
  var payload = {
336
- remote_host: options.remote_host,
337
- ssh_port: (_a = options.ssh_port) !== null && _a !== void 0 ? _a : 33001,
338
- timeout_sec: (_b = options.timeout_sec) !== null && _b !== void 0 ? _b : 3,
405
+ request: {
406
+ remote_host: options.remote_host,
407
+ ssh_port: (_a = options.ssh_port) !== null && _a !== void 0 ? _a : 33001,
408
+ timeout_sec: (_b = options.timeout_sec) !== null && _b !== void 0 ? _b : 3,
409
+ }
339
410
  };
340
411
  client_1.client.request('test_ssh_ports', payload)
341
412
  .then(function (data) { return promiseInfo.resolver(data); })
@@ -400,9 +471,10 @@ var startTransfer = function (transferSpec, asperaSdkSpec) {
400
471
  'Connect dialogs block all subsequent HTTP responses. ' +
401
472
  'Set `allow_dialogs: false` explicitly to suppress this warning. ' +
402
473
  'More info: https://github.com/IBM/aspera-sdk-js/issues/196');
403
- asperaSdkSpec = __assign(__assign({}, asperaSdkSpec), { allow_dialogs: false });
474
+ asperaSdkSpec.allow_dialogs = false;
404
475
  }
405
476
  return index_1.asperaSdk.globals.connect.startTransferPromise(transferSpec, asperaSdkSpec).then(function (response) {
477
+ response.transfer_specs[0].transfer_client = 'connect';
406
478
  return response.transfer_specs[0];
407
479
  });
408
480
  }
@@ -416,7 +488,10 @@ var startTransfer = function (transferSpec, asperaSdkSpec) {
416
488
  app_id: index_1.asperaSdk.globals.appId,
417
489
  };
418
490
  client_1.client.request('start_transfer', payload)
419
- .then(function (data) { return promiseInfo.resolver(data); })
491
+ .then(function (data) {
492
+ data.transfer_client = 'desktop';
493
+ promiseInfo.resolver(data);
494
+ })
420
495
  .catch(function (error) {
421
496
  (0, helpers_1.errorLog)(messages_1.messages.transferFailed, error);
422
497
  promiseInfo.rejecter((0, helpers_1.generateErrorBody)(messages_1.messages.transferFailed, error));
@@ -567,6 +642,7 @@ exports.stopTransfer = stopTransfer;
567
642
  var resumeTransfer = function (id, options) {
568
643
  if (index_1.asperaSdk.useConnect) {
569
644
  return index_1.asperaSdk.globals.connect.resumeTransfer(id, options).then(function (response) {
645
+ response.transfer_spec.transfer_client = 'connect';
570
646
  return response.transfer_spec;
571
647
  });
572
648
  }
@@ -579,7 +655,10 @@ var resumeTransfer = function (id, options) {
579
655
  transfer_spec: options,
580
656
  };
581
657
  client_1.client.request('resume_transfer', payload)
582
- .then(function (data) { return promiseInfo.resolver(data); })
658
+ .then(function (data) {
659
+ data.transfer_client = 'desktop';
660
+ promiseInfo.resolver(data);
661
+ })
583
662
  .catch(function (error) {
584
663
  (0, helpers_1.errorLog)(messages_1.messages.resumeTransferFailed, error);
585
664
  promiseInfo.rejecter((0, helpers_1.generateErrorBody)(messages_1.messages.resumeTransferFailed, error));
@@ -852,6 +931,9 @@ var getAllTransfers = function () {
852
931
  else if (index_1.asperaSdk.useConnect) {
853
932
  index_1.asperaSdk.globals.connect.getAllTransfers({
854
933
  success: function (data) {
934
+ data.transfers.forEach(function (t) {
935
+ t.transfer_client = 'connect';
936
+ });
855
937
  promiseInfo.resolver(data.transfers);
856
938
  }, error: function (error) {
857
939
  promiseInfo.rejecter(error);
@@ -866,7 +948,12 @@ var getAllTransfers = function () {
866
948
  app_id: index_1.asperaSdk.globals.appId,
867
949
  };
868
950
  client_1.client.request('get_all_transfers', payload)
869
- .then(function (data) { return promiseInfo.resolver(data); })
951
+ .then(function (data) {
952
+ data.forEach(function (t) {
953
+ t.transfer_client = 'desktop';
954
+ });
955
+ promiseInfo.resolver(data);
956
+ })
870
957
  .catch(function (error) {
871
958
  (0, helpers_1.errorLog)(messages_1.messages.getAllTransfersFailed, error);
872
959
  promiseInfo.rejecter((0, helpers_1.generateErrorBody)(messages_1.messages.getAllTransfersFailed, error));
@@ -893,6 +980,7 @@ var getTransfer = function (id) {
893
980
  }
894
981
  else if (index_1.asperaSdk.useConnect) {
895
982
  return index_1.asperaSdk.globals.connect.getTransfer(id).then(function (response) {
983
+ response.transfer_info.transfer_client = 'connect';
896
984
  return response.transfer_info;
897
985
  });
898
986
  }
@@ -904,7 +992,10 @@ var getTransfer = function (id) {
904
992
  transfer_id: id,
905
993
  };
906
994
  client_1.client.request('get_transfer', payload)
907
- .then(function (data) { return promiseInfo.resolver(data); })
995
+ .then(function (data) {
996
+ data.transfer_client = 'desktop';
997
+ promiseInfo.resolver(data);
998
+ })
908
999
  .catch(function (error) {
909
1000
  (0, helpers_1.errorLog)(messages_1.messages.getTransferFailed, error);
910
1001
  promiseInfo.rejecter((0, helpers_1.generateErrorBody)(messages_1.messages.getTransferFailed, error));
@@ -1428,3 +1519,15 @@ var hasCapability = function (capability) {
1428
1519
  return !!(0, exports.getCapabilities)()[capability];
1429
1520
  };
1430
1521
  exports.hasCapability = hasCapability;
1522
+ var currentTransferClient = function () {
1523
+ if (index_1.asperaSdk.useHttpGateway) {
1524
+ return 'http-gateway';
1525
+ }
1526
+ else if (index_1.asperaSdk.useConnect) {
1527
+ return 'connect';
1528
+ }
1529
+ else if (index_1.asperaSdk.isReady) {
1530
+ return 'desktop';
1531
+ }
1532
+ };
1533
+ exports.currentTransferClient = currentTransferClient;
@@ -15,8 +15,18 @@ declare class StatusService {
15
15
  * @param detectFn async function that resolves if Desktop is found, rejects if not
16
16
  * @param interval ms between attempts
17
17
  * @param failTimeout ms before transitioning to FAILED or DEGRADED
18
+ * @param onFallback optional callback invoked on timeout instead of FAILED/DEGRADED (e.g. to start Connect)
18
19
  */
19
- startPolling(detectFn: () => Promise<void>, interval: number, failTimeout: number): void;
20
+ startPolling(detectFn: () => Promise<void>, interval: number, failTimeout: number, onFallback?: () => void): void;
21
+ /**
22
+ * Resume Desktop detection polling without resetting status or setting a fail timeout.
23
+ * Used after a fallback decision (e.g. FAILED/DEGRADED) to continue detecting Desktop
24
+ * in the background so a late launch can still transition to RUNNING.
25
+ *
26
+ * @param detectFn async function that resolves if Desktop is found, rejects if not
27
+ * @param interval ms between attempts
28
+ */
29
+ resumePolling(detectFn: () => Promise<void>, interval: number): void;
20
30
  stopPolling(): void;
21
31
  reset(): void;
22
32
  }
@@ -14,8 +14,8 @@ var StatusService = /** @class */ (function () {
14
14
  return this.currentStatus;
15
15
  };
16
16
  StatusService.prototype.setStatus = function (status) {
17
- // When Desktop disconnects, remap to DEGRADED if HTTP Gateway is available
18
- if (status === 'DISCONNECTED' && index_1.asperaSdk.httpGatewayIsReady) {
17
+ // When Desktop disconnects or transfer client fails, remap to DEGRADED if HTTP Gateway is available
18
+ if ((status === 'DISCONNECTED' || status === 'FAILED') && index_1.asperaSdk.httpGatewayIsReady) {
19
19
  status = 'DEGRADED';
20
20
  }
21
21
  if (this.currentStatus === status) {
@@ -48,14 +48,19 @@ var StatusService = /** @class */ (function () {
48
48
  * @param detectFn async function that resolves if Desktop is found, rejects if not
49
49
  * @param interval ms between attempts
50
50
  * @param failTimeout ms before transitioning to FAILED or DEGRADED
51
+ * @param onFallback optional callback invoked on timeout instead of FAILED/DEGRADED (e.g. to start Connect)
51
52
  */
52
- StatusService.prototype.startPolling = function (detectFn, interval, failTimeout) {
53
+ StatusService.prototype.startPolling = function (detectFn, interval, failTimeout, onFallback) {
53
54
  var _this = this;
54
55
  this.stopPolling();
55
56
  this.setStatus('INITIALIZING');
56
57
  this.failTimeoutId = setTimeout(function () {
57
58
  if (_this.currentStatus !== 'RUNNING') {
58
- if (index_1.asperaSdk.httpGatewayIsReady) {
59
+ if (onFallback) {
60
+ _this.stopPolling();
61
+ onFallback();
62
+ }
63
+ else if (index_1.asperaSdk.httpGatewayIsReady) {
59
64
  _this.setStatus('DEGRADED');
60
65
  }
61
66
  else {
@@ -76,6 +81,32 @@ var StatusService = /** @class */ (function () {
76
81
  attempt();
77
82
  this.pollTimerId = setInterval(attempt, interval);
78
83
  };
84
+ /**
85
+ * Resume Desktop detection polling without resetting status or setting a fail timeout.
86
+ * Used after a fallback decision (e.g. FAILED/DEGRADED) to continue detecting Desktop
87
+ * in the background so a late launch can still transition to RUNNING.
88
+ *
89
+ * @param detectFn async function that resolves if Desktop is found, rejects if not
90
+ * @param interval ms between attempts
91
+ */
92
+ StatusService.prototype.resumePolling = function (detectFn, interval) {
93
+ var _this = this;
94
+ if (this.pollTimerId) {
95
+ return;
96
+ }
97
+ var attempt = function () {
98
+ detectFn()
99
+ .then(function () {
100
+ _this.stopPolling();
101
+ _this.setStatus('RUNNING');
102
+ })
103
+ .catch(function () {
104
+ // Stay in current status, poll continues
105
+ });
106
+ };
107
+ attempt();
108
+ this.pollTimerId = setInterval(attempt, interval);
109
+ };
79
110
  StatusService.prototype.stopPolling = function () {
80
111
  if (this.pollTimerId) {
81
112
  clearInterval(this.pollTimerId);
@@ -13,6 +13,9 @@ var installerFlowActivated = false;
13
13
  * You may not need to import anything from this file.
14
14
  */
15
15
  var handleTransfers = function (transfers) {
16
+ transfers.forEach(function (t) {
17
+ t.transfer_client = 'connect';
18
+ });
16
19
  index_1.asperaSdk.activityTracking.handleTransferActivity({
17
20
  type: 'transferUpdated',
18
21
  data: { transfers: transfers },
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Lightweight check for the Connect browser extension.
3
+ * Does NOT launch Connect — only checks if the extension is installed.
4
+ *
5
+ * Chrome/Firefox/Edge: dispatches AsperaConnectCheck, listens for window message
6
+ * Safari: dispatches AsperaConnectCheck, listens for document event
7
+ */
8
+ export declare const detectConnectExtension: (timeoutMs: number) => Promise<boolean>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectConnectExtension = void 0;
4
+ var helpers_1 = require("./helpers");
5
+ /**
6
+ * Lightweight check for the Connect browser extension.
7
+ * Does NOT launch Connect — only checks if the extension is installed.
8
+ *
9
+ * Chrome/Firefox/Edge: dispatches AsperaConnectCheck, listens for window message
10
+ * Safari: dispatches AsperaConnectCheck, listens for document event
11
+ */
12
+ var detectConnectExtension = function (timeoutMs) {
13
+ return new Promise(function (resolve) {
14
+ var resolved = false;
15
+ var timer = setTimeout(function () {
16
+ if (!resolved) {
17
+ resolved = true;
18
+ resolve(false);
19
+ }
20
+ }, timeoutMs);
21
+ if ((0, helpers_1.isSafari)()) {
22
+ var handler_1 = function () {
23
+ if (!resolved) {
24
+ resolved = true;
25
+ clearTimeout(timer);
26
+ document.removeEventListener('AsperaConnectCheckResponse', handler_1);
27
+ resolve(true);
28
+ }
29
+ };
30
+ document.addEventListener('AsperaConnectCheckResponse', handler_1);
31
+ }
32
+ else {
33
+ var handler_2 = function (evt) {
34
+ var _a;
35
+ if (!resolved &&
36
+ typeof evt.data === 'object' &&
37
+ ((_a = evt.data) === null || _a === void 0 ? void 0 : _a.type) === 'AsperaConnectCheckResponse') {
38
+ resolved = true;
39
+ clearTimeout(timer);
40
+ window.removeEventListener('message', handler_2);
41
+ resolve(true);
42
+ }
43
+ };
44
+ window.addEventListener('message', handler_2);
45
+ }
46
+ // Poll interval self-cleans via the resolved flag
47
+ var poll = setInterval(function () {
48
+ if (resolved) {
49
+ clearInterval(poll);
50
+ return;
51
+ }
52
+ document.dispatchEvent(new CustomEvent('AsperaConnectCheck'));
53
+ }, 200);
54
+ // Fire immediately
55
+ document.dispatchEvent(new CustomEvent('AsperaConnectCheck'));
56
+ });
57
+ };
58
+ exports.detectConnectExtension = detectConnectExtension;
@@ -91,6 +91,11 @@ export declare const safeJsonString: (json: unknown) => string;
91
91
  * @returns object or array from the JSON string. Or undefined
92
92
  */
93
93
  export declare const safeJsonParse: (json: string) => any | undefined;
94
+ /**
95
+ * Race a promise against a timeout. Rejects with an Error('timeout') if the
96
+ * given milliseconds elapse before the promise settles.
97
+ */
98
+ export declare const withTimeout: <T>(promise: Promise<T>, ms: number) => Promise<T>;
94
99
  declare const _default: {
95
100
  errorLog: (message: string, debugData?: any) => void;
96
101
  generateErrorBody: (message: string, debugData?: any) => ErrorResponse;
@@ -105,5 +110,6 @@ declare const _default: {
105
110
  getInstallerUrls: () => InstallerUrlInfo;
106
111
  safeJsonString: (json: unknown) => string;
107
112
  safeJsonParse: (json: string) => any | undefined;
113
+ withTimeout: <T>(promise: Promise<T>, ms: number) => Promise<T>;
108
114
  };
109
115
  export default _default;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.safeJsonParse = exports.safeJsonString = exports.getInstallerUrls = exports.isSafari = exports.isValidURL = exports.throwError = exports.randomUUID = exports.getCurrentPlatform = exports.getWebsocketUrl = exports.isValidTransferSpec = exports.generateErrorBody = exports.errorLog = exports.generatePromiseObjects = void 0;
3
+ exports.withTimeout = exports.safeJsonParse = exports.safeJsonString = exports.getInstallerUrls = exports.isSafari = exports.isValidURL = exports.throwError = exports.randomUUID = exports.getCurrentPlatform = exports.getWebsocketUrl = exports.isValidTransferSpec = exports.generateErrorBody = exports.errorLog = exports.generatePromiseObjects = void 0;
4
4
  var constants_1 = require("../constants/constants");
5
5
  /**
6
6
  * Generates promise object that can be resolved or rejected via functions
@@ -232,6 +232,23 @@ var safeJsonParse = function (json) {
232
232
  }
233
233
  };
234
234
  exports.safeJsonParse = safeJsonParse;
235
+ /**
236
+ * Race a promise against a timeout. Rejects with an Error('timeout') if the
237
+ * given milliseconds elapse before the promise settles.
238
+ */
239
+ var withTimeout = function (promise, ms) {
240
+ return new Promise(function (resolve, reject) {
241
+ var timer = setTimeout(function () { return reject(new Error('timeout')); }, ms);
242
+ promise.then(function (val) {
243
+ clearTimeout(timer);
244
+ resolve(val);
245
+ }, function (err) {
246
+ clearTimeout(timer);
247
+ reject(err);
248
+ });
249
+ });
250
+ };
251
+ exports.withTimeout = withTimeout;
235
252
  exports.default = {
236
253
  errorLog: exports.errorLog,
237
254
  generateErrorBody: exports.generateErrorBody,
@@ -246,4 +263,5 @@ exports.default = {
246
263
  getInstallerUrls: exports.getInstallerUrls,
247
264
  safeJsonString: exports.safeJsonString,
248
265
  safeJsonParse: exports.safeJsonParse,
266
+ withTimeout: exports.withTimeout,
249
267
  };
@@ -8,6 +8,12 @@ export declare class WebsocketService {
8
8
  private eventListener;
9
9
  /** Indicator if the websocket is already connected */
10
10
  private isConnected;
11
+ /** When true, the reconnect loop is suppressed */
12
+ private stopped;
13
+ /** When true, the connection/reconnect loop is already running */
14
+ private active;
15
+ /** ID of the pending reconnect timer (so it can be cancelled) */
16
+ private reconnectTimerId;
11
17
  /** Global promise object that resolves when init completes */
12
18
  private initPromise;
13
19
  /** Log call for not being ready */
@@ -52,6 +58,11 @@ export declare class WebsocketService {
52
58
  * @returns a promise that resolves when the websocket connection is established
53
59
  */
54
60
  init(): Promise<unknown>;
61
+ /**
62
+ * Stop the WebSocket connection and suppress the automatic reconnect loop.
63
+ * Used when falling back to a different transfer client (e.g. Connect).
64
+ */
65
+ disconnect(): void;
55
66
  private connect;
56
67
  /**
57
68
  * Detach event handlers from the current socket so it cannot fire
@@ -11,6 +11,12 @@ var WebsocketService = /** @class */ (function () {
11
11
  this.sockets = new Map();
12
12
  /** Indicator if the websocket is already connected */
13
13
  this.isConnected = false;
14
+ /** When true, the reconnect loop is suppressed */
15
+ this.stopped = false;
16
+ /** When true, the connection/reconnect loop is already running */
17
+ this.active = false;
18
+ /** ID of the pending reconnect timer (so it can be cancelled) */
19
+ this.reconnectTimerId = null;
14
20
  /** Global promise object that resolves when init completes */
15
21
  this.initPromise = (0, helpers_1.generatePromiseObjects)();
16
22
  /**
@@ -104,9 +110,32 @@ var WebsocketService = /** @class */ (function () {
104
110
  * @returns a promise that resolves when the websocket connection is established
105
111
  */
106
112
  WebsocketService.prototype.init = function () {
107
- this.connect();
113
+ this.stopped = false;
114
+ if (!this.active) {
115
+ this.active = true;
116
+ this.connect();
117
+ }
108
118
  return this.initPromise.promise;
109
119
  };
120
+ /**
121
+ * Stop the WebSocket connection and suppress the automatic reconnect loop.
122
+ * Used when falling back to a different transfer client (e.g. Connect).
123
+ */
124
+ WebsocketService.prototype.disconnect = function () {
125
+ this.stopped = true;
126
+ this.active = false;
127
+ if (this.reconnectTimerId) {
128
+ clearTimeout(this.reconnectTimerId);
129
+ this.reconnectTimerId = null;
130
+ }
131
+ this.detachSocket();
132
+ if (this.globalSocket) {
133
+ this.globalSocket.close();
134
+ this.globalSocket = null;
135
+ }
136
+ this.isConnected = false;
137
+ this.initPromise = (0, helpers_1.generatePromiseObjects)();
138
+ };
110
139
  WebsocketService.prototype.connect = function () {
111
140
  var _this = this;
112
141
  this.detachSocket();
@@ -136,11 +165,15 @@ var WebsocketService = /** @class */ (function () {
136
165
  };
137
166
  WebsocketService.prototype.reconnect = function () {
138
167
  var _this = this;
168
+ if (this.stopped) {
169
+ return;
170
+ }
139
171
  this.detachSocket();
140
172
  if (this.globalSocket) {
141
173
  this.globalSocket.close();
142
174
  }
143
- setTimeout(function () {
175
+ this.reconnectTimerId = setTimeout(function () {
176
+ _this.reconnectTimerId = null;
144
177
  _this.connect();
145
178
  }, 1000);
146
179
  };