@ibm-aspera/sdk 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/commonjs/app/core.d.ts +43 -17
  2. package/dist/commonjs/app/core.js +144 -28
  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 +16 -0
  11. package/dist/commonjs/helpers/ws.js +49 -2
  12. package/dist/commonjs/http-gateway/core.js +10 -12
  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 +10 -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
  44. package/scripts/release.sh +7 -7
  45. package/scripts/version.sh +24 -15
@@ -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
138
+ * initSession({
139
+ * appId: 'my-app',
140
+ * httpGatewaySettings: {
141
+ * url: 'https://example.com/aspera/http-gwy',
142
+ * },
143
+ * });
144
+ *
145
+ * * @example
146
+ * // Use IBM Aspera for desktop or IBM Aspera Connect with automatic fallback to HTTP Gateway
133
147
  * initSession({
134
148
  * appId: 'my-app',
149
+ * connectSettings: {
150
+ * fallback: true,
151
+ * },
135
152
  * httpGatewaySettings: {
136
153
  * url: 'https://example.com/aspera/http-gwy',
137
- * forceGateway: false,
138
154
  * },
139
155
  * });
140
156
  */
@@ -437,11 +453,12 @@ export declare const readDirectory: (options: ReadDirectoryOptions) => Promise<R
437
453
  * Returns an object describing the high-level capabilities supported by the user's
438
454
  * transfer client (e.g. IBM Aspera for desktop, Connect, or HTTP Gateway).
439
455
  *
440
- * Use this for feature detection at a semantic level rather than checking individual RPC methods.
441
- * Capabitilies may depend on multiple underlying RPC methods and also may vary by transfer client.
456
+ * Use this for feature detection at a semantic level as capabilities may change depending on the
457
+ * transfer client.
442
458
  *
443
- * Some capabitilies may depend on newer versions of the transfer client. This function may be useful
444
- * if you want to conditionally perform certain actions rather than potentially getting an error.
459
+ * Rather than caching the return value of this function, it's recommended to call it on the fly as
460
+ * capabilities may change if your application supports multiple transfer clients. As a result, it's
461
+ * recommend to use the slightly more ergonomic {@link hasCapability}.
445
462
  *
446
463
  * @returns an object with boolean flags for each capability.
447
464
  *
@@ -455,10 +472,18 @@ export declare const readDirectory: (options: ReadDirectoryOptions) => Promise<R
455
472
  */
456
473
  export declare const getCapabilities: () => SdkCapabilities;
457
474
  /**
458
- * Check if the SDK and underlying transfer client supports a specific capability.
475
+ * Check if the SDK and underlying transfer client supports a specific capability or feature.
459
476
  *
460
477
  * Capabilities depend on the transfer client being used (HTTP Gateway, Connect, or IBM Aspera for desktop).
461
- * Use this function to conditionally enable/disable features in your application.
478
+ *
479
+ * This function may be useful if you want to conditionally perform certain actions rather than
480
+ * potentially getting an error.
481
+ *
482
+ * For example, only IBM Aspera for desktop supports traversing a folder's contents. An application can
483
+ * check `hasCapability('readDirectory')` to optionally show a folder browser only when the feature is available.
484
+ * For example, when a user does not have IBM Aspera for desktop installed and is using HTTP Gateway, your
485
+ * application can disable this feature. Later, if that same user installs IBM Aspera for desktop, your application
486
+ * will show the feature as enabled without any additional changes.
462
487
  *
463
488
  * @param capability the capability to check.
464
489
  *
@@ -468,8 +493,9 @@ export declare const getCapabilities: () => SdkCapabilities;
468
493
  * ```typescript
469
494
  * // Determine if your web application can render image previews for user selected files
470
495
  * if (asperaSdk.hasCapability('imagePreview')) {
471
- * asperaSdk.readAsArrayBuffer(path);
496
+ * const response = await asperaSdk.readAsArrayBuffer(path);
472
497
  * }
473
498
  * ```
474
499
  */
475
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
290
+ * initSession({
291
+ * appId: 'my-app',
292
+ * httpGatewaySettings: {
293
+ * url: 'https://example.com/aspera/http-gwy',
294
+ * },
295
+ * });
296
+ *
297
+ * * @example
298
+ * // Use IBM Aspera for desktop or IBM Aspera Connect with automatic fallback to HTTP Gateway
265
299
  * initSession({
266
300
  * appId: 'my-app',
301
+ * connectSettings: {
302
+ * fallback: true,
303
+ * },
267
304
  * httpGatewaySettings: {
268
305
  * url: 'https://example.com/aspera/http-gwy',
269
- * forceGateway: false,
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));
@@ -1342,6 +1433,10 @@ var readDirectory = function (options) {
1342
1433
  };
1343
1434
  exports.readDirectory = readDirectory;
1344
1435
  var supportsMethod = function (method) {
1436
+ // HTTP Gateway v2 specific overrides
1437
+ if (index_1.asperaSdk.useOldHttpGateway && (method === 'read_as_array_buffer' || method === 'read_chunk_as_array_buffer')) {
1438
+ return false;
1439
+ }
1345
1440
  // We currently do not support calculating file checksums when using HTTP Gateway. In theory it should be possible
1346
1441
  // to calculate this directly in the browser similar to how `readAsArrayBuffer()` is implemented.
1347
1442
  // HTTP Gateway also does not support showing native transfer client UI (about, preferences, etc.).
@@ -1362,11 +1457,12 @@ var supportsMethod = function (method) {
1362
1457
  * Returns an object describing the high-level capabilities supported by the user's
1363
1458
  * transfer client (e.g. IBM Aspera for desktop, Connect, or HTTP Gateway).
1364
1459
  *
1365
- * Use this for feature detection at a semantic level rather than checking individual RPC methods.
1366
- * Capabitilies may depend on multiple underlying RPC methods and also may vary by transfer client.
1460
+ * Use this for feature detection at a semantic level as capabilities may change depending on the
1461
+ * transfer client.
1367
1462
  *
1368
- * Some capabitilies may depend on newer versions of the transfer client. This function may be useful
1369
- * if you want to conditionally perform certain actions rather than potentially getting an error.
1463
+ * Rather than caching the return value of this function, it's recommended to call it on the fly as
1464
+ * capabilities may change if your application supports multiple transfer clients. As a result, it's
1465
+ * recommend to use the slightly more ergonomic {@link hasCapability}.
1370
1466
  *
1371
1467
  * @returns an object with boolean flags for each capability.
1372
1468
  *
@@ -1394,10 +1490,18 @@ var getCapabilities = function () {
1394
1490
  };
1395
1491
  exports.getCapabilities = getCapabilities;
1396
1492
  /**
1397
- * Check if the SDK and underlying transfer client supports a specific capability.
1493
+ * Check if the SDK and underlying transfer client supports a specific capability or feature.
1398
1494
  *
1399
1495
  * Capabilities depend on the transfer client being used (HTTP Gateway, Connect, or IBM Aspera for desktop).
1400
- * Use this function to conditionally enable/disable features in your application.
1496
+ *
1497
+ * This function may be useful if you want to conditionally perform certain actions rather than
1498
+ * potentially getting an error.
1499
+ *
1500
+ * For example, only IBM Aspera for desktop supports traversing a folder's contents. An application can
1501
+ * check `hasCapability('readDirectory')` to optionally show a folder browser only when the feature is available.
1502
+ * For example, when a user does not have IBM Aspera for desktop installed and is using HTTP Gateway, your
1503
+ * application can disable this feature. Later, if that same user installs IBM Aspera for desktop, your application
1504
+ * will show the feature as enabled without any additional changes.
1401
1505
  *
1402
1506
  * @param capability the capability to check.
1403
1507
  *
@@ -1407,7 +1511,7 @@ exports.getCapabilities = getCapabilities;
1407
1511
  * ```typescript
1408
1512
  * // Determine if your web application can render image previews for user selected files
1409
1513
  * if (asperaSdk.hasCapability('imagePreview')) {
1410
- * asperaSdk.readAsArrayBuffer(path);
1514
+ * const response = await asperaSdk.readAsArrayBuffer(path);
1411
1515
  * }
1412
1516
  * ```
1413
1517
  */
@@ -1415,3 +1519,15 @@ var hasCapability = function (capability) {
1415
1519
  return !!(0, exports.getCapabilities)()[capability];
1416
1520
  };
1417
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;