@openeo/js-client 2.0.1 → 2.3.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.
- package/README.md +4 -3
- package/openeo.d.ts +198 -72
- package/openeo.js +5111 -7402
- package/openeo.min.js +1 -1
- package/package.json +8 -7
- package/src/authprovider.js +1 -1
- package/src/baseentity.js +3 -1
- package/src/builder/builder.js +79 -51
- package/src/builder/formula.js +1 -0
- package/src/builder/node.js +13 -4
- package/src/builder/parameter.js +2 -3
- package/src/builder/tapdigit.js +11 -3
- package/src/capabilities.js +1 -1
- package/src/connection.js +171 -42
- package/src/filetypes.js +3 -3
- package/src/job.js +3 -0
- package/src/oidcprovider.js +5 -5
- package/src/openeo.js +14 -7
- package/src/typedefs.js +13 -3
- package/src/userfile.js +3 -2
- package/src/userprocess.js +9 -1
- package/CHANGELOG.md +0 -125
package/src/connection.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const Environment = require('./env');
|
|
2
2
|
const Utils = require('@openeo/js-commons/src/utils');
|
|
3
|
+
const ProcessRegistry = require('@openeo/js-commons/src/processRegistry');
|
|
3
4
|
const axios = require('axios').default;
|
|
4
5
|
const StacMigrate = require('@radiantearth/stac-migrate');
|
|
5
6
|
|
|
@@ -25,33 +26,77 @@ class Connection {
|
|
|
25
26
|
/**
|
|
26
27
|
* Creates a new Connection.
|
|
27
28
|
*
|
|
28
|
-
* @param {string} baseUrl - URL
|
|
29
|
+
* @param {string} baseUrl - The versioned URL or the back-end instance.
|
|
30
|
+
* @param {Options} [options={}] - Additional options for the connection.
|
|
31
|
+
* @param {?string} [url=null] - User-provided URL of the backend connected to.
|
|
29
32
|
*/
|
|
30
|
-
constructor(baseUrl) {
|
|
33
|
+
constructor(baseUrl, options = {}, url = null) {
|
|
31
34
|
/**
|
|
35
|
+
* User-provided URL of the backend connected to.
|
|
36
|
+
*
|
|
37
|
+
* `null` if not given and the connection was directly made to a versioned instance of the back-end.
|
|
38
|
+
*
|
|
39
|
+
* @protected
|
|
40
|
+
* @type {string | null}
|
|
41
|
+
*/
|
|
42
|
+
this.url = url;
|
|
43
|
+
/**
|
|
44
|
+
* The versioned URL or the back-end instance.
|
|
45
|
+
*
|
|
46
|
+
* @protected
|
|
32
47
|
* @type {string}
|
|
33
48
|
*/
|
|
34
49
|
this.baseUrl = Utils.normalizeUrl(baseUrl);
|
|
35
50
|
/**
|
|
51
|
+
* Auth Provider cache
|
|
52
|
+
*
|
|
53
|
+
* @protected
|
|
36
54
|
* @type {?Array.<AuthProvider>}
|
|
37
55
|
*/
|
|
38
56
|
this.authProviderList = null;
|
|
39
57
|
/**
|
|
58
|
+
* Current auth provider
|
|
59
|
+
*
|
|
60
|
+
* @protected
|
|
40
61
|
* @type {?AuthProvider}
|
|
41
62
|
*/
|
|
42
63
|
this.authProvider = null;
|
|
43
64
|
/**
|
|
65
|
+
* Capability cache
|
|
66
|
+
*
|
|
67
|
+
* @protected
|
|
44
68
|
* @type {?Capabilities}
|
|
45
69
|
*/
|
|
46
70
|
this.capabilitiesObject = null;
|
|
47
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Listeners for events.
|
|
73
|
+
*
|
|
74
|
+
* @protected
|
|
75
|
+
* @type {object.<string|Function>}
|
|
76
|
+
*/
|
|
48
77
|
this.listeners = {};
|
|
78
|
+
/**
|
|
79
|
+
* Additional options for the connection.
|
|
80
|
+
*
|
|
81
|
+
* @protected
|
|
82
|
+
* @type {Options}
|
|
83
|
+
*/
|
|
84
|
+
this.options = options;
|
|
85
|
+
/**
|
|
86
|
+
* Process cache
|
|
87
|
+
*
|
|
88
|
+
* @protected
|
|
89
|
+
* @type {ProcessRegistry}
|
|
90
|
+
*/
|
|
91
|
+
this.processes = new ProcessRegistry([], Boolean(options.addNamespaceToProcess));
|
|
92
|
+
this.processes.listeners.push((...args) => this.emit('processesChanged', ...args));
|
|
49
93
|
}
|
|
50
94
|
|
|
51
95
|
/**
|
|
52
96
|
* Initializes the connection by requesting the capabilities.
|
|
53
97
|
*
|
|
54
98
|
* @async
|
|
99
|
+
* @protected
|
|
55
100
|
* @returns {Promise<Capabilities>} Capabilities
|
|
56
101
|
*/
|
|
57
102
|
async init() {
|
|
@@ -61,14 +106,52 @@ class Connection {
|
|
|
61
106
|
}
|
|
62
107
|
|
|
63
108
|
/**
|
|
64
|
-
*
|
|
109
|
+
* Refresh the cache for processes.
|
|
65
110
|
*
|
|
66
|
-
* @
|
|
111
|
+
* @async
|
|
112
|
+
* @protected
|
|
113
|
+
* @returns {Promise}
|
|
114
|
+
*/
|
|
115
|
+
async refreshProcessCache() {
|
|
116
|
+
if (this.processes.count() === 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
let promises = this.processes.namespaces().map(namespace => {
|
|
120
|
+
let fn = () => Promise.resolve();
|
|
121
|
+
if (namespace === 'user') {
|
|
122
|
+
if (!this.isAuthenticated()) {
|
|
123
|
+
fn = () => (this.processes.remove(null, 'user') ? Promise.resolve() : Promise.reject(new Error("Can't clear user processes")));
|
|
124
|
+
}
|
|
125
|
+
else if (this.capabilities().hasFeature('listUserProcesses')) {
|
|
126
|
+
fn = () => this.listUserProcesses();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else if (this.capabilities().hasFeature('listProcesses')) {
|
|
130
|
+
fn = () => this.listProcesses(namespace);
|
|
131
|
+
}
|
|
132
|
+
return fn().catch(error => console.warn(`Could not update processes for namespace '${namespace}' due to an error: ${error.message}`));
|
|
133
|
+
});
|
|
134
|
+
return await Promise.all(promises);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns the URL of the versioned back-end instance currently connected to.
|
|
139
|
+
*
|
|
140
|
+
* @returns {string} The versioned URL or the back-end instance.
|
|
67
141
|
*/
|
|
68
142
|
getBaseUrl() {
|
|
69
143
|
return this.baseUrl;
|
|
70
144
|
}
|
|
71
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Returns the user-provided URL of the back-end currently connected to.
|
|
148
|
+
*
|
|
149
|
+
* @returns {string} The URL or the back-end.
|
|
150
|
+
*/
|
|
151
|
+
getUrl() {
|
|
152
|
+
return this.url || this.baseUrl;
|
|
153
|
+
}
|
|
154
|
+
|
|
72
155
|
/**
|
|
73
156
|
* Returns the capabilities of the back-end.
|
|
74
157
|
*
|
|
@@ -156,16 +239,16 @@ class Connection {
|
|
|
156
239
|
*
|
|
157
240
|
* @async
|
|
158
241
|
* @param {string} collectionId - Collection ID to request items for.
|
|
159
|
-
* @param {?Array.<number>} spatialExtent - Limits the items to the given bounding box in WGS84:
|
|
242
|
+
* @param {?Array.<number>} [spatialExtent=null] - Limits the items to the given bounding box in WGS84:
|
|
160
243
|
* 1. Lower left corner, coordinate axis 1
|
|
161
244
|
* 2. Lower left corner, coordinate axis 2
|
|
162
245
|
* 3. Upper right corner, coordinate axis 1
|
|
163
246
|
* 4. Upper right corner, coordinate axis 2
|
|
164
|
-
* @param {?Array.<*>} temporalExtent - Limits the items to the specified temporal interval.
|
|
247
|
+
* @param {?Array.<*>} [temporalExtent=null] - Limits the items to the specified temporal interval.
|
|
165
248
|
* The interval has to be specified as an array with exactly two elements (start, end) and
|
|
166
249
|
* each must be either an RFC 3339 compatible string or a Date object.
|
|
167
250
|
* Also supports open intervals by setting one of the boundaries to `null`, but never both.
|
|
168
|
-
* @param {?number} limit - The amount of items per request/page as integer. If `null` (default), the back-end decides.
|
|
251
|
+
* @param {?number} [limit=null] - The amount of items per request/page as integer. If `null` (default), the back-end decides.
|
|
169
252
|
* @yields {Promise<ItemCollection>} A response compatible to the API specification.
|
|
170
253
|
* @throws {Error}
|
|
171
254
|
*/
|
|
@@ -208,20 +291,35 @@ class Connection {
|
|
|
208
291
|
}
|
|
209
292
|
|
|
210
293
|
/**
|
|
211
|
-
* List
|
|
294
|
+
* List processes available on the back-end.
|
|
295
|
+
*
|
|
296
|
+
* Requests pre-defined processes by default.
|
|
297
|
+
* Set the namespace parameter to request processes from a specific namespace.
|
|
212
298
|
*
|
|
213
|
-
*
|
|
299
|
+
* Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given.
|
|
300
|
+
* The namespaces are then listed in the property `namespaces`.
|
|
214
301
|
*
|
|
215
302
|
* @async
|
|
303
|
+
* @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
|
|
216
304
|
* @returns {Promise<Processes>} - A response compatible to the API specification.
|
|
217
305
|
* @throws {Error}
|
|
218
306
|
*/
|
|
219
|
-
async listProcesses() {
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
this.processes = response.data;
|
|
307
|
+
async listProcesses(namespace = null) {
|
|
308
|
+
if (!namespace) {
|
|
309
|
+
namespace = 'backend';
|
|
223
310
|
}
|
|
224
|
-
|
|
311
|
+
let path = (namespace === 'backend') ? '/processes' : `/processes/${namespace}`;
|
|
312
|
+
let response = await this._get(path);
|
|
313
|
+
|
|
314
|
+
if (!Utils.isObject(response.data) || !Array.isArray(response.data.processes)) {
|
|
315
|
+
throw new Error('Invalid response received for processes');
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Store processes in cache
|
|
319
|
+
this.processes.remove(null, namespace);
|
|
320
|
+
this.processes.addAll(response.data.processes, namespace);
|
|
321
|
+
|
|
322
|
+
return Object.assign(response.data, {processes: this.processes.namespace(namespace)});
|
|
225
323
|
}
|
|
226
324
|
|
|
227
325
|
/**
|
|
@@ -229,20 +327,30 @@ class Connection {
|
|
|
229
327
|
*
|
|
230
328
|
* @async
|
|
231
329
|
* @param {string} processId - Collection ID to request further metadata for.
|
|
330
|
+
* @param {?string} [namespace=null] - Namespace of the process (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
|
|
232
331
|
* @returns {Promise<?Process>} - A single process as object, or `null` if none is found.
|
|
233
332
|
* @throws {Error}
|
|
234
333
|
* @see Connection#listProcesses
|
|
235
334
|
*/
|
|
236
|
-
async describeProcess(processId) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return response.processes.find(process => Utils.isObject(process) && process.id === processId) || null;
|
|
335
|
+
async describeProcess(processId, namespace = null) {
|
|
336
|
+
if (!namespace) {
|
|
337
|
+
namespace = 'backend';
|
|
240
338
|
}
|
|
241
|
-
|
|
339
|
+
if (namespace === 'backend') {
|
|
340
|
+
await this.listProcesses();
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
let response = await this._get(`/processes/${namespace}/${processId}`);
|
|
344
|
+
if (!Utils.isObject(response.data) || typeof response.data.id !== 'string') {
|
|
345
|
+
throw new Error('Invalid response received for process');
|
|
346
|
+
}
|
|
347
|
+
this.processes.add(response.data, namespace);
|
|
348
|
+
}
|
|
349
|
+
return this.processes.get(processId, namespace);
|
|
242
350
|
}
|
|
243
351
|
|
|
244
352
|
/**
|
|
245
|
-
* Returns an object to simply build user-defined processes.
|
|
353
|
+
* Returns an object to simply build user-defined processes based upon pre-defined processes.
|
|
246
354
|
*
|
|
247
355
|
* @async
|
|
248
356
|
* @param {string} id - A name for the process.
|
|
@@ -251,8 +359,8 @@ class Connection {
|
|
|
251
359
|
* @see Connection#listProcesses
|
|
252
360
|
*/
|
|
253
361
|
async buildProcess(id) {
|
|
254
|
-
|
|
255
|
-
return new Builder(
|
|
362
|
+
await this.listProcesses();
|
|
363
|
+
return new Builder(this.processes, null, id);
|
|
256
364
|
}
|
|
257
365
|
|
|
258
366
|
/**
|
|
@@ -305,7 +413,7 @@ class Connection {
|
|
|
305
413
|
*
|
|
306
414
|
* @callback oidcProviderFactoryFunction
|
|
307
415
|
* @param {object.<string, *>} providerInfo - The provider information as provided by the API, having the properties `id`, `issuer`, `title` etc.
|
|
308
|
-
* @returns {
|
|
416
|
+
* @returns {AuthProvider | null}
|
|
309
417
|
*/
|
|
310
418
|
|
|
311
419
|
/**
|
|
@@ -315,7 +423,7 @@ class Connection {
|
|
|
315
423
|
* on the AuthProvider interface (or OIDCProvider class), e.g. to use a
|
|
316
424
|
* OIDC library other than oidc-client-js.
|
|
317
425
|
*
|
|
318
|
-
* @param {?oidcProviderFactoryFunction} providerFactoryFunc
|
|
426
|
+
* @param {?oidcProviderFactoryFunction} [providerFactoryFunc=null]
|
|
319
427
|
* @see AuthProvider
|
|
320
428
|
*/
|
|
321
429
|
setOidcProviderFactory(providerFactoryFunc) {
|
|
@@ -328,7 +436,7 @@ class Connection {
|
|
|
328
436
|
* Returns `null` if OIDC is not supported by the client or an instance
|
|
329
437
|
* can't be created for whatever reason.
|
|
330
438
|
*
|
|
331
|
-
* @returns {
|
|
439
|
+
* @returns {oidcProviderFactoryFunction | null}
|
|
332
440
|
* @see AuthProvider
|
|
333
441
|
*/
|
|
334
442
|
getOidcProviderFactory() {
|
|
@@ -390,6 +498,7 @@ class Connection {
|
|
|
390
498
|
* Currently supported:
|
|
391
499
|
* - authProviderChanged(provider): Raised when the auth provider has changed.
|
|
392
500
|
* - tokenChanged(token): Raised when the access token has changed.
|
|
501
|
+
* - processesChanged(type, data, namespace): Raised when the process registry has changed (i.e. a process was added, updated or deleted).
|
|
393
502
|
*
|
|
394
503
|
* @param {string} event
|
|
395
504
|
* @param {Function} callback
|
|
@@ -410,7 +519,7 @@ class Connection {
|
|
|
410
519
|
/**
|
|
411
520
|
* Returns the AuthProvider.
|
|
412
521
|
*
|
|
413
|
-
* @returns {
|
|
522
|
+
* @returns {AuthProvider | null}
|
|
414
523
|
*/
|
|
415
524
|
getAuthProvider() {
|
|
416
525
|
return this.authProvider;
|
|
@@ -432,6 +541,8 @@ class Connection {
|
|
|
432
541
|
this.authProvider = null;
|
|
433
542
|
}
|
|
434
543
|
this.emit('authProviderChanged', this.authProvider);
|
|
544
|
+
// Update process cache on auth changes: https://github.com/Open-EO/openeo-js-client/issues/55
|
|
545
|
+
this.refreshProcessCache();
|
|
435
546
|
}
|
|
436
547
|
|
|
437
548
|
/**
|
|
@@ -487,12 +598,12 @@ class Connection {
|
|
|
487
598
|
);
|
|
488
599
|
}
|
|
489
600
|
|
|
490
|
-
|
|
491
601
|
/**
|
|
492
602
|
* A callback that is executed on upload progress updates.
|
|
493
603
|
*
|
|
494
604
|
* @callback uploadStatusCallback
|
|
495
605
|
* @param {number} percentCompleted - The percent (0-100) completed.
|
|
606
|
+
* @param {UserFile} file - The file object corresponding to the callback.
|
|
496
607
|
*/
|
|
497
608
|
|
|
498
609
|
/**
|
|
@@ -507,15 +618,16 @@ class Connection {
|
|
|
507
618
|
* @param {*} source - The source, see method description for details.
|
|
508
619
|
* @param {?string} [targetPath=null] - The target path on the server, relative to the user workspace. Defaults to the file name of the source file.
|
|
509
620
|
* @param {?uploadStatusCallback} [statusCallback=null] - Optionally, a callback that is executed on upload progress updates.
|
|
621
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the upload process.
|
|
510
622
|
* @returns {Promise<UserFile>}
|
|
511
623
|
* @throws {Error}
|
|
512
624
|
*/
|
|
513
|
-
async uploadFile(source, targetPath = null, statusCallback = null) {
|
|
625
|
+
async uploadFile(source, targetPath = null, statusCallback = null, abortController = null) {
|
|
514
626
|
if (targetPath === null) {
|
|
515
627
|
targetPath = Environment.fileNameForUpload(source);
|
|
516
628
|
}
|
|
517
629
|
let file = await this.getFile(targetPath);
|
|
518
|
-
return await file.uploadFile(source, statusCallback);
|
|
630
|
+
return await file.uploadFile(source, statusCallback, abortController);
|
|
519
631
|
}
|
|
520
632
|
|
|
521
633
|
/**
|
|
@@ -582,6 +694,15 @@ class Connection {
|
|
|
582
694
|
*/
|
|
583
695
|
async listUserProcesses() {
|
|
584
696
|
let response = await this._get('/process_graphs');
|
|
697
|
+
|
|
698
|
+
if (!Utils.isObject(response.data) || !Array.isArray(response.data.processes)) {
|
|
699
|
+
throw new Error('Invalid response received for processes');
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Store processes in cache
|
|
703
|
+
this.processes.remove(null, 'user');
|
|
704
|
+
this.processes.addAll(response.data.processes, 'user');
|
|
705
|
+
|
|
585
706
|
return response.data.processes.map(
|
|
586
707
|
pg => new UserProcess(this, pg.id).setAll(pg)
|
|
587
708
|
);
|
|
@@ -623,9 +744,10 @@ class Connection {
|
|
|
623
744
|
* @param {Process} process - A user-defined process.
|
|
624
745
|
* @param {?string} [plan=null] - The billing plan to use for this computation.
|
|
625
746
|
* @param {?number} [budget=null] - The maximum budget allowed to spend for this computation.
|
|
747
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the processing request.
|
|
626
748
|
* @returns {Promise<SyncResult>} - An object with the data and some metadata.
|
|
627
749
|
*/
|
|
628
|
-
async computeResult(process, plan = null, budget = null) {
|
|
750
|
+
async computeResult(process, plan = null, budget = null, abortController = null) {
|
|
629
751
|
let requestBody = this._normalizeUserProcess(
|
|
630
752
|
process,
|
|
631
753
|
{
|
|
@@ -633,7 +755,7 @@ class Connection {
|
|
|
633
755
|
budget: budget
|
|
634
756
|
}
|
|
635
757
|
);
|
|
636
|
-
let response = await this._post('/result', requestBody, Environment.getResponseType());
|
|
758
|
+
let response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
|
|
637
759
|
let syncResult = {
|
|
638
760
|
data: response.data,
|
|
639
761
|
costs: null,
|
|
@@ -684,10 +806,11 @@ class Connection {
|
|
|
684
806
|
* @param {string} targetPath - The target, see method description for details.
|
|
685
807
|
* @param {?string} [plan=null] - The billing plan to use for this computation.
|
|
686
808
|
* @param {?number} [budget=null] - The maximum budget allowed to spend for this computation.
|
|
809
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the processing request.
|
|
687
810
|
* @throws {Error}
|
|
688
811
|
*/
|
|
689
|
-
async downloadResult(process, targetPath, plan = null, budget = null) {
|
|
690
|
-
let response = await this.computeResult(process, plan, budget);
|
|
812
|
+
async downloadResult(process, targetPath, plan = null, budget = null, abortController = null) {
|
|
813
|
+
let response = await this.computeResult(process, plan, budget, abortController);
|
|
691
814
|
// @ts-ignore
|
|
692
815
|
await Environment.saveToFile(response.data, targetPath);
|
|
693
816
|
}
|
|
@@ -732,7 +855,7 @@ class Connection {
|
|
|
732
855
|
throw new Error("Response did not contain a Job ID. Job has likely been created, but may not show up yet.");
|
|
733
856
|
}
|
|
734
857
|
let job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
|
|
735
|
-
if (this.
|
|
858
|
+
if (this.capabilities().hasFeature('describeJob')) {
|
|
736
859
|
return await job.describeJob();
|
|
737
860
|
}
|
|
738
861
|
else {
|
|
@@ -798,7 +921,7 @@ class Connection {
|
|
|
798
921
|
throw new Error("Response did not contain a Service ID. Service has likely been created, but may not show up yet.");
|
|
799
922
|
}
|
|
800
923
|
let service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
|
|
801
|
-
if (this.
|
|
924
|
+
if (this.capabilities().hasFeature('describeService')) {
|
|
802
925
|
return service.describeService();
|
|
803
926
|
}
|
|
804
927
|
else {
|
|
@@ -824,7 +947,7 @@ class Connection {
|
|
|
824
947
|
*
|
|
825
948
|
* @param {Array.<Link>} links - An array of links.
|
|
826
949
|
* @param {string} rel - Relation type to find, defaults to `next`.
|
|
827
|
-
* @returns {
|
|
950
|
+
* @returns {string | null}
|
|
828
951
|
* @throws {Error}
|
|
829
952
|
*/
|
|
830
953
|
_getLinkHref(links, rel = 'next') {
|
|
@@ -855,7 +978,7 @@ class Connection {
|
|
|
855
978
|
url: path,
|
|
856
979
|
// Timeout for capabilities requests as they are used for a quick first discovery to check whether the server is a openEO back-end.
|
|
857
980
|
// Without timeout connecting with a wrong server url may take forever.
|
|
858
|
-
timeout: path === '/' ?
|
|
981
|
+
timeout: path === '/' ? 5000 : 0,
|
|
859
982
|
params: query
|
|
860
983
|
});
|
|
861
984
|
}
|
|
@@ -867,17 +990,19 @@ class Connection {
|
|
|
867
990
|
* @param {string} path
|
|
868
991
|
* @param {*} body
|
|
869
992
|
* @param {string} responseType - Response type according to axios, defaults to `json`.
|
|
993
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the request.
|
|
870
994
|
* @returns {Promise<AxiosResponse>}
|
|
871
995
|
* @throws {Error}
|
|
872
996
|
* @see https://github.com/axios/axios#request-config
|
|
873
997
|
*/
|
|
874
|
-
async _post(path, body, responseType) {
|
|
875
|
-
|
|
998
|
+
async _post(path, body, responseType, abortController = null) {
|
|
999
|
+
let options = {
|
|
876
1000
|
method: 'post',
|
|
877
1001
|
responseType: responseType,
|
|
878
1002
|
url: path,
|
|
879
1003
|
data: body
|
|
880
|
-
}
|
|
1004
|
+
};
|
|
1005
|
+
return await this._send(options, abortController);
|
|
881
1006
|
}
|
|
882
1007
|
|
|
883
1008
|
/**
|
|
@@ -963,11 +1088,12 @@ class Connection {
|
|
|
963
1088
|
*
|
|
964
1089
|
* @async
|
|
965
1090
|
* @param {object.<string, *>} options
|
|
1091
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the request.
|
|
966
1092
|
* @returns {Promise<AxiosResponse>}
|
|
967
1093
|
* @throws {Error}
|
|
968
1094
|
* @see https://github.com/axios/axios
|
|
969
1095
|
*/
|
|
970
|
-
async _send(options) {
|
|
1096
|
+
async _send(options, abortController = null) {
|
|
971
1097
|
options.baseURL = this.baseUrl;
|
|
972
1098
|
if (this.isAuthenticated() && (typeof options.authorization === 'undefined' || options.authorization === true)) {
|
|
973
1099
|
if (!options.headers) {
|
|
@@ -978,6 +1104,9 @@ class Connection {
|
|
|
978
1104
|
if (!options.responseType) {
|
|
979
1105
|
options.responseType = 'json';
|
|
980
1106
|
}
|
|
1107
|
+
if (abortController) {
|
|
1108
|
+
options.signal = abortController.signal;
|
|
1109
|
+
}
|
|
981
1110
|
|
|
982
1111
|
try {
|
|
983
1112
|
return await axios(options);
|
package/src/filetypes.js
CHANGED
|
@@ -64,7 +64,7 @@ class FileTypes {
|
|
|
64
64
|
* Returns null if no input file format was found for the given identifier.
|
|
65
65
|
*
|
|
66
66
|
* @param {string} type - Case-insensitive file format identifier
|
|
67
|
-
* @returns {
|
|
67
|
+
* @returns {FileType | null}
|
|
68
68
|
*/
|
|
69
69
|
getInputType(type) {
|
|
70
70
|
return this._findType(type, 'input');
|
|
@@ -76,7 +76,7 @@ class FileTypes {
|
|
|
76
76
|
* Returns null if no output file format was found for the given identifier.
|
|
77
77
|
*
|
|
78
78
|
* @param {string} type - Case-insensitive file format identifier
|
|
79
|
-
* @returns {
|
|
79
|
+
* @returns {FileType | null}
|
|
80
80
|
*/
|
|
81
81
|
getOutputType(type) {
|
|
82
82
|
return this._findType(type, 'output');
|
|
@@ -87,7 +87,7 @@ class FileTypes {
|
|
|
87
87
|
*
|
|
88
88
|
* @param {string} type - Identifier of the file type
|
|
89
89
|
* @param {string} io - Either `input` or `output`
|
|
90
|
-
* @returns {
|
|
90
|
+
* @returns {FileType | null}
|
|
91
91
|
* @protected
|
|
92
92
|
*/
|
|
93
93
|
_findType(type, io) {
|
package/src/job.js
CHANGED
|
@@ -265,6 +265,9 @@ class Job extends BaseEntity {
|
|
|
265
265
|
*/
|
|
266
266
|
async getResultsAsStac() {
|
|
267
267
|
let response = await this.connection._get('/jobs/' + this.id + '/results');
|
|
268
|
+
if (!Utils.isObject(response) || !Utils.isObject(response.data)) {
|
|
269
|
+
throw new Error("Results received from the back-end are invalid");
|
|
270
|
+
}
|
|
268
271
|
let data = StacMigrate.stac(response.data);
|
|
269
272
|
if (!Utils.isObject(data.assets)) {
|
|
270
273
|
data.assets = {};
|
package/src/oidcprovider.js
CHANGED
|
@@ -132,8 +132,8 @@ class OidcProvider extends AuthProvider {
|
|
|
132
132
|
* Adds a listener to one of the following events:
|
|
133
133
|
*
|
|
134
134
|
* - AccessTokenExpiring: Raised prior to the access token expiring.
|
|
135
|
-
* -
|
|
136
|
-
* -
|
|
135
|
+
* - AccessTokenExpired: Raised after the access token has expired.
|
|
136
|
+
* - SilentRenewError: Raised when the automatic silent renew has failed.
|
|
137
137
|
*
|
|
138
138
|
* @param {string} event
|
|
139
139
|
* @param {Function} callback
|
|
@@ -271,7 +271,7 @@ class OidcProvider extends AuthProvider {
|
|
|
271
271
|
*
|
|
272
272
|
* This may override a detected default client ID.
|
|
273
273
|
*
|
|
274
|
-
* @param {
|
|
274
|
+
* @param {string | null} clientId
|
|
275
275
|
*/
|
|
276
276
|
setClientId(clientId) {
|
|
277
277
|
this.clientId = clientId;
|
|
@@ -281,7 +281,7 @@ class OidcProvider extends AuthProvider {
|
|
|
281
281
|
* Sets the OIDC User.
|
|
282
282
|
*
|
|
283
283
|
* @see https://github.com/IdentityModel/oidc-client-js/wiki#user
|
|
284
|
-
* @param {
|
|
284
|
+
* @param {Oidc.User | null} user - The OIDC User. Passing `null` resets OIDC authentication details.
|
|
285
285
|
*/
|
|
286
286
|
setUser(user) {
|
|
287
287
|
if (!user) {
|
|
@@ -299,7 +299,7 @@ class OidcProvider extends AuthProvider {
|
|
|
299
299
|
*
|
|
300
300
|
* Sets the grant and client ID accordingly.
|
|
301
301
|
*
|
|
302
|
-
* @returns {
|
|
302
|
+
* @returns {OidcClient | null}
|
|
303
303
|
* @see OidcProvider#setGrant
|
|
304
304
|
* @see OidcProvider#setClientId
|
|
305
305
|
*/
|
package/src/openeo.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const axios = require('axios').default;
|
|
2
|
+
const { AbortController } = require("node-abort-controller");
|
|
2
3
|
const Utils = require('@openeo/js-commons/src/utils');
|
|
3
4
|
const Versions = require('@openeo/js-commons/src/versions');
|
|
4
5
|
|
|
@@ -43,15 +44,17 @@ class OpenEO {
|
|
|
43
44
|
*
|
|
44
45
|
* @async
|
|
45
46
|
* @param {string} url - The server URL to connect to.
|
|
47
|
+
* @param {Options} [options={}] - Additional options for the connection.
|
|
46
48
|
* @returns {Promise<Connection>}
|
|
47
49
|
* @throws {Error}
|
|
48
50
|
* @static
|
|
49
51
|
*/
|
|
50
|
-
static async connect(url) {
|
|
52
|
+
static async connect(url, options = {}) {
|
|
51
53
|
let wellKnownUrl = Utils.normalizeUrl(url, '/.well-known/openeo');
|
|
54
|
+
let versionedUrl = url;
|
|
52
55
|
let response = null;
|
|
53
56
|
try {
|
|
54
|
-
response = await axios.get(wellKnownUrl);
|
|
57
|
+
response = await axios.get(wellKnownUrl, {timeout: 5000});
|
|
55
58
|
|
|
56
59
|
if (!Utils.isObject(response.data) || !Array.isArray(response.data.versions)) {
|
|
57
60
|
throw new Error("Well-Known Document doesn't list any versions.");
|
|
@@ -63,14 +66,16 @@ class OpenEO {
|
|
|
63
66
|
if (Utils.isObject(response)) {
|
|
64
67
|
let version = Versions.findLatest(response.data.versions, true, MIN_API_VERSION, MAX_API_VERSION);
|
|
65
68
|
if (version !== null) {
|
|
66
|
-
|
|
69
|
+
versionedUrl = version.url;
|
|
67
70
|
}
|
|
68
71
|
else {
|
|
69
72
|
throw new Error("Server not supported. Client only supports the API versions between " + MIN_API_VERSION + " and " + MAX_API_VERSION);
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
let connection = await OpenEO.connectDirect(versionedUrl, options);
|
|
77
|
+
connection.url = url;
|
|
78
|
+
return connection;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
/**
|
|
@@ -80,12 +85,13 @@ class OpenEO {
|
|
|
80
85
|
*
|
|
81
86
|
* @async
|
|
82
87
|
* @param {string} versionedUrl - The server URL to connect to.
|
|
88
|
+
* @param {Options} [options={}] - Additional options for the connection.
|
|
83
89
|
* @returns {Promise<Connection>}
|
|
84
90
|
* @throws {Error}
|
|
85
91
|
* @static
|
|
86
92
|
*/
|
|
87
|
-
static async connectDirect(versionedUrl) {
|
|
88
|
-
let connection = new Connection(versionedUrl);
|
|
93
|
+
static async connectDirect(versionedUrl, options = {}) {
|
|
94
|
+
let connection = new Connection(versionedUrl, options);
|
|
89
95
|
|
|
90
96
|
// Check whether back-end is accessible and supports a compatible version.
|
|
91
97
|
let capabilities = await connection.init();
|
|
@@ -104,7 +110,7 @@ class OpenEO {
|
|
|
104
110
|
* @returns {string} Version number (according to SemVer).
|
|
105
111
|
*/
|
|
106
112
|
static clientVersion() {
|
|
107
|
-
return "2.
|
|
113
|
+
return "2.3.1";
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
}
|
|
@@ -112,6 +118,7 @@ class OpenEO {
|
|
|
112
118
|
OpenEO.Environment = require('./env');
|
|
113
119
|
|
|
114
120
|
module.exports = {
|
|
121
|
+
AbortController,
|
|
115
122
|
AuthProvider,
|
|
116
123
|
BasicProvider,
|
|
117
124
|
Capabilities,
|
package/src/typedefs.js
CHANGED
|
@@ -170,11 +170,20 @@
|
|
|
170
170
|
* @property {Array.<Link>} links Links
|
|
171
171
|
*/
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Connection options.
|
|
175
|
+
*
|
|
176
|
+
* @typedef Options
|
|
177
|
+
* @type {object}
|
|
178
|
+
* @property {boolean} addNamespaceToProcess Add a namespace property to processes if set to `true`. Defaults to `false`.
|
|
179
|
+
*/
|
|
180
|
+
|
|
173
181
|
/**
|
|
174
182
|
* @typedef Processes
|
|
175
183
|
* @type {object}
|
|
176
184
|
* @property {Array.<Process>} processes
|
|
177
185
|
* @property {Array.<Link>} links
|
|
186
|
+
* @property {?Array.<string>} namespaces EXPERIMENTAL!
|
|
178
187
|
*/
|
|
179
188
|
|
|
180
189
|
/**
|
|
@@ -214,8 +223,9 @@
|
|
|
214
223
|
* @typedef UserAccount
|
|
215
224
|
* @type {object}
|
|
216
225
|
* @property {string} user_id
|
|
217
|
-
* @property {string} name
|
|
218
|
-
* @property {
|
|
226
|
+
* @property {?string} name
|
|
227
|
+
* @property {?string} default_plan
|
|
228
|
+
* @property {?UserAccountStorage} storage
|
|
219
229
|
* @property {?number} budget
|
|
220
|
-
* @property {Array.<Link>} links
|
|
230
|
+
* @property {?Array.<Link>} links
|
|
221
231
|
*/
|
package/src/userfile.js
CHANGED
|
@@ -90,10 +90,11 @@ class UserFile extends BaseEntity {
|
|
|
90
90
|
* @async
|
|
91
91
|
* @param {*} source - The source, see method description for details.
|
|
92
92
|
* @param {?uploadStatusCallback} statusCallback - Optionally, a callback that is executed on upload progress updates.
|
|
93
|
+
* @param {?AbortController} [abortController=null] - An AbortController object that can be used to cancel the upload process.
|
|
93
94
|
* @returns {Promise<UserFile>}
|
|
94
95
|
* @throws {Error}
|
|
95
96
|
*/
|
|
96
|
-
async uploadFile(source, statusCallback = null) {
|
|
97
|
+
async uploadFile(source, statusCallback = null, abortController = null) {
|
|
97
98
|
let options = {
|
|
98
99
|
method: 'put',
|
|
99
100
|
url: '/files/' + this.path,
|
|
@@ -109,7 +110,7 @@ class UserFile extends BaseEntity {
|
|
|
109
110
|
};
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
let response = await this.connection._send(options);
|
|
113
|
+
let response = await this.connection._send(options, abortController);
|
|
113
114
|
return this.setAll(response.data);
|
|
114
115
|
}
|
|
115
116
|
|