@openeo/js-client 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/openeo.d.ts +203 -24
- package/openeo.js +1851 -1187
- package/openeo.min.js +1 -1
- package/package.json +2 -2
- package/src/capabilities.js +9 -0
- package/src/connection.js +159 -179
- package/src/env.js +13 -3
- package/src/logs.js +36 -0
- package/src/openeo.js +1 -1
- package/src/pages.js +349 -0
- package/src/typedefs.js +30 -2
package/src/env.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
let Environment = null;
|
|
1
2
|
if (typeof window === 'undefined') {
|
|
2
|
-
|
|
3
|
+
Environment = require('./node');
|
|
3
4
|
}
|
|
4
5
|
else {
|
|
5
|
-
|
|
6
|
-
}
|
|
6
|
+
Environment = require('./browser');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The axios instance to use for HTTP requests.
|
|
10
|
+
*
|
|
11
|
+
* @type {object}
|
|
12
|
+
* @static
|
|
13
|
+
*/
|
|
14
|
+
Environment.axios = require('axios');
|
|
15
|
+
|
|
16
|
+
module.exports = Environment;
|
package/src/logs.js
CHANGED
|
@@ -18,9 +18,26 @@ class Logs {
|
|
|
18
18
|
* @type {Connection}
|
|
19
19
|
*/
|
|
20
20
|
this.connection = connection;
|
|
21
|
+
/**
|
|
22
|
+
* @protected
|
|
23
|
+
* @type {string}
|
|
24
|
+
*/
|
|
21
25
|
this.endpoint = endpoint;
|
|
26
|
+
/**
|
|
27
|
+
* @protected
|
|
28
|
+
* @type {string}
|
|
29
|
+
*/
|
|
22
30
|
this.lastId = "";
|
|
31
|
+
/**
|
|
32
|
+
* @protected
|
|
33
|
+
* @type {?string}
|
|
34
|
+
*/
|
|
23
35
|
this.level = level;
|
|
36
|
+
/**
|
|
37
|
+
* @protected
|
|
38
|
+
* @type {Set<string>}
|
|
39
|
+
*/
|
|
40
|
+
this.missing = new Set();
|
|
24
41
|
}
|
|
25
42
|
|
|
26
43
|
/**
|
|
@@ -37,6 +54,19 @@ class Logs {
|
|
|
37
54
|
return Array.isArray(response.logs) ? response.logs : [];
|
|
38
55
|
}
|
|
39
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Retrieves the backend identifiers that are (partially) missing in the logs.
|
|
59
|
+
*
|
|
60
|
+
* This is only filled after the first request using `nextLogs` or `next`.
|
|
61
|
+
*
|
|
62
|
+
* @returns {Array.<string>}
|
|
63
|
+
* @see {Logs#nextLogs}
|
|
64
|
+
* @see {Logs#next}
|
|
65
|
+
*/
|
|
66
|
+
getMissingBackends() {
|
|
67
|
+
return Array.from(this.missing);
|
|
68
|
+
}
|
|
69
|
+
|
|
40
70
|
/**
|
|
41
71
|
* Retrieves the next log entries since the last request.
|
|
42
72
|
*
|
|
@@ -64,7 +94,13 @@ class Logs {
|
|
|
64
94
|
else {
|
|
65
95
|
response.data.logs = [];
|
|
66
96
|
}
|
|
97
|
+
|
|
67
98
|
response.data.links = Array.isArray(response.data.links) ? response.data.links : [];
|
|
99
|
+
|
|
100
|
+
if (Array.isArray(response.data["federation:missing"])) {
|
|
101
|
+
response.data["federation:missing"].forEach(backend => this.missing.add(backend));
|
|
102
|
+
}
|
|
103
|
+
|
|
68
104
|
return response.data;
|
|
69
105
|
}
|
|
70
106
|
|
package/src/openeo.js
CHANGED
package/src/pages.js
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/* eslint-disable max-classes-per-file */
|
|
2
|
+
|
|
3
|
+
const Job = require('./job.js');
|
|
4
|
+
const Service = require('./service.js');
|
|
5
|
+
const UserFile = require('./userfile.js');
|
|
6
|
+
const UserProcess = require('./userprocess.js');
|
|
7
|
+
const Utils = require('@openeo/js-commons/src/utils');
|
|
8
|
+
const StacMigrate = require('@radiantearth/stac-migrate');
|
|
9
|
+
|
|
10
|
+
const FED_MISSING = 'federation:missing';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A class to handle pagination of resources.
|
|
14
|
+
*
|
|
15
|
+
* @abstract
|
|
16
|
+
*/
|
|
17
|
+
class Pages {
|
|
18
|
+
/**
|
|
19
|
+
* Creates an instance of Pages.
|
|
20
|
+
*
|
|
21
|
+
* @param {Connection} connection
|
|
22
|
+
* @param {string} endpoint
|
|
23
|
+
* @param {string} key
|
|
24
|
+
* @param {Constructor} cls
|
|
25
|
+
* @param {object} [params={}]
|
|
26
|
+
* @param {string} primaryKey
|
|
27
|
+
*/
|
|
28
|
+
constructor(connection, endpoint, key, cls, params = {}, primaryKey = "id") {
|
|
29
|
+
this.connection = connection;
|
|
30
|
+
this.nextUrl = endpoint;
|
|
31
|
+
this.key = key;
|
|
32
|
+
this.primaryKey = primaryKey;
|
|
33
|
+
this.cls = cls;
|
|
34
|
+
if (!(params.limit > 0)) {
|
|
35
|
+
delete params.limit;
|
|
36
|
+
}
|
|
37
|
+
this.params = params;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns true if there are more pages to fetch.
|
|
42
|
+
*
|
|
43
|
+
* @returns {boolean}
|
|
44
|
+
*/
|
|
45
|
+
hasNextPage() {
|
|
46
|
+
return this.nextUrl !== null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns the next page of resources.
|
|
51
|
+
*
|
|
52
|
+
* @async
|
|
53
|
+
* @param {Array.<object>} oldObjects - Existing objects to update, if any.
|
|
54
|
+
* @param {boolean} [toArray=true] - Whether to return the objects as a simplified array or as an object with all information.
|
|
55
|
+
* @returns {Array.<object>}
|
|
56
|
+
* @throws {Error}
|
|
57
|
+
*/
|
|
58
|
+
async nextPage(oldObjects = [], toArray = true) {
|
|
59
|
+
// Request data from server
|
|
60
|
+
const response = await this.connection._get(this.nextUrl, this.params);
|
|
61
|
+
|
|
62
|
+
let data = response.data;
|
|
63
|
+
// Check response
|
|
64
|
+
if (!Utils.isObject(data)) {
|
|
65
|
+
throw new Error(`Response is invalid, is not an object`);
|
|
66
|
+
}
|
|
67
|
+
if (!Array.isArray(data[this.key])) {
|
|
68
|
+
throw new Error(`Response is invalid, '${this.key}' property is not an array`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Update existing objects if needed
|
|
72
|
+
let newObjects = data[this.key].map(updated => {
|
|
73
|
+
let resource = oldObjects.find(old => old[this.primaryKey] === updated[this.primaryKey]);
|
|
74
|
+
if (resource) {
|
|
75
|
+
resource.setAll(updated);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
resource = this._createObject(updated);
|
|
79
|
+
}
|
|
80
|
+
return resource;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Store objects in cache if needed
|
|
84
|
+
newObjects = this._cache(newObjects);
|
|
85
|
+
|
|
86
|
+
// Add self link if missing
|
|
87
|
+
data.links = this._ensureArray(data.links);
|
|
88
|
+
const selfLink = this.connection._getLinkHref(data.links, 'self');
|
|
89
|
+
if (!selfLink) {
|
|
90
|
+
data.links.push({rel: 'self', href: this.nextUrl});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check whether a next page is available
|
|
94
|
+
this.nextUrl = this._getNextLink(response);
|
|
95
|
+
// Don't append initial params to the next URL
|
|
96
|
+
this.params = null;
|
|
97
|
+
|
|
98
|
+
// Either return as ResponseArray or full API response body
|
|
99
|
+
if (toArray) {
|
|
100
|
+
newObjects.links = data.links;
|
|
101
|
+
newObjects[FED_MISSING] = this._ensureArray(data[FED_MISSING]);
|
|
102
|
+
return newObjects;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
data[this.key] = newObjects;
|
|
106
|
+
return data;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Ensures a variable is an array.
|
|
112
|
+
*
|
|
113
|
+
* @protected
|
|
114
|
+
* @param {*} x
|
|
115
|
+
* @returns {Array}
|
|
116
|
+
*/
|
|
117
|
+
_ensureArray(x) {
|
|
118
|
+
return Array.isArray(x) ? x : [];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Creates a facade for the object, if needed.
|
|
123
|
+
*
|
|
124
|
+
* @protected
|
|
125
|
+
* @param {object} obj
|
|
126
|
+
* @returns {object}
|
|
127
|
+
*/
|
|
128
|
+
_createObject(obj) {
|
|
129
|
+
if (this.cls) {
|
|
130
|
+
const cls = this.cls;
|
|
131
|
+
const newObj = new cls(this.connection, obj[this.primaryKey]);
|
|
132
|
+
newObj.setAll(obj);
|
|
133
|
+
return newObj;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
return obj;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Caches the plain objects if needed.
|
|
142
|
+
*
|
|
143
|
+
* @param {Array.<object>} objects
|
|
144
|
+
* @returns {Array.<object>}
|
|
145
|
+
*/
|
|
146
|
+
_cache(objects) {
|
|
147
|
+
return objects;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the URL of the next page from a response.
|
|
152
|
+
*
|
|
153
|
+
* @protected
|
|
154
|
+
* @param {AxiosResponse} response
|
|
155
|
+
* @returns {string | null}
|
|
156
|
+
*/
|
|
157
|
+
_getNextLink(response) {
|
|
158
|
+
const links = this.connection.makeLinksAbsolute(response.data.links, response);
|
|
159
|
+
return this.connection._getLinkHref(links, 'next');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Makes this class asynchronously iterable.
|
|
164
|
+
*
|
|
165
|
+
* @returns {AsyncIterator}
|
|
166
|
+
*/
|
|
167
|
+
[Symbol.asyncIterator]() {
|
|
168
|
+
return {
|
|
169
|
+
self: this,
|
|
170
|
+
/**
|
|
171
|
+
* Get the next page of resources.
|
|
172
|
+
*
|
|
173
|
+
* @async
|
|
174
|
+
* @returns {{done: boolean, value: Array.<object>}}
|
|
175
|
+
*/
|
|
176
|
+
async next() {
|
|
177
|
+
const done = !this.self.hasNextPage();
|
|
178
|
+
let value;
|
|
179
|
+
if (!done) {
|
|
180
|
+
value = await this.self.nextPage();
|
|
181
|
+
}
|
|
182
|
+
return { done, value };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Paginate through jobs.
|
|
191
|
+
*/
|
|
192
|
+
class JobPages extends Pages {
|
|
193
|
+
/**
|
|
194
|
+
* Paginate through jobs.
|
|
195
|
+
*
|
|
196
|
+
* @param {Connection} connection
|
|
197
|
+
* @param {?number} limit
|
|
198
|
+
*/
|
|
199
|
+
constructor(connection, limit = null) {
|
|
200
|
+
super(connection, "/jobs", "jobs", Job, {limit});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Paginate through services.
|
|
206
|
+
*/
|
|
207
|
+
class ServicePages extends Pages {
|
|
208
|
+
/**
|
|
209
|
+
* Paginate through services.
|
|
210
|
+
*
|
|
211
|
+
* @param {Connection} connection
|
|
212
|
+
* @param {?number} limit
|
|
213
|
+
*/
|
|
214
|
+
constructor(connection, limit = null) {
|
|
215
|
+
super(connection, "/services", "services", Service, {limit});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Paginate through user files.
|
|
221
|
+
*/
|
|
222
|
+
class UserFilePages extends Pages {
|
|
223
|
+
/**
|
|
224
|
+
* Paginate through user files.
|
|
225
|
+
*
|
|
226
|
+
* @param {Connection} connection
|
|
227
|
+
* @param {?number} limit
|
|
228
|
+
*/
|
|
229
|
+
constructor(connection, limit = null) {
|
|
230
|
+
super(connection, "/files", "files", UserFile, {limit}, "path");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Paginate through processes.
|
|
236
|
+
*/
|
|
237
|
+
class ProcessPages extends Pages {
|
|
238
|
+
/**
|
|
239
|
+
* Paginate through processes.
|
|
240
|
+
*
|
|
241
|
+
* @param {Connection} connection
|
|
242
|
+
* @param {?number} limit
|
|
243
|
+
* @param {?string} namespace
|
|
244
|
+
*/
|
|
245
|
+
constructor(connection, limit = null, namespace = null) {
|
|
246
|
+
if (!namespace) {
|
|
247
|
+
namespace = 'backend';
|
|
248
|
+
}
|
|
249
|
+
let endpoint;
|
|
250
|
+
let cls = null
|
|
251
|
+
if (namespace === 'user') {
|
|
252
|
+
endpoint = '/process_graphs';
|
|
253
|
+
cls = UserProcess;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
endpoint = '/processes';
|
|
257
|
+
if (namespace !== 'backend') {
|
|
258
|
+
const normalized = connection.normalizeNamespace(namespace);
|
|
259
|
+
endpoint += `/${normalized}`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
super(connection, endpoint, "processes", cls, {limit});
|
|
263
|
+
this.namespace = namespace;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Caches the objects to the ProcessRegistry.
|
|
268
|
+
*
|
|
269
|
+
* @param {Array.<object>} objects
|
|
270
|
+
* @returns {Array.<object>}
|
|
271
|
+
*/
|
|
272
|
+
_cache(objects) {
|
|
273
|
+
const plainObjects = objects.map(p => (typeof p.toJSON === 'function' ? p.toJSON() : p));
|
|
274
|
+
this.connection.processes.addAll(plainObjects, this.namespace);
|
|
275
|
+
if (!this.cls) {
|
|
276
|
+
for (let i in objects) {
|
|
277
|
+
objects[i] = this.connection.processes.get(objects[i].id, this.namespace);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return objects;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Paginate through collections.
|
|
286
|
+
*/
|
|
287
|
+
class CollectionPages extends Pages {
|
|
288
|
+
/**
|
|
289
|
+
* Paginate through collections.
|
|
290
|
+
*
|
|
291
|
+
* @param {Connection} connection
|
|
292
|
+
* @param {?number} limit
|
|
293
|
+
*/
|
|
294
|
+
constructor(connection, limit = null) {
|
|
295
|
+
super(connection, "/collections", "collections", null, {limit});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Migrates the STAC collection to the latest version.
|
|
300
|
+
*
|
|
301
|
+
* @param {object} obj
|
|
302
|
+
* @returns {Collection}
|
|
303
|
+
*/
|
|
304
|
+
_createObject(obj) {
|
|
305
|
+
if (obj.stac_version) {
|
|
306
|
+
return StacMigrate.collection(obj);
|
|
307
|
+
}
|
|
308
|
+
return obj;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Paginate through collection items.
|
|
314
|
+
*/
|
|
315
|
+
class ItemPages extends Pages {
|
|
316
|
+
/**
|
|
317
|
+
* Paginate through collection items.
|
|
318
|
+
*
|
|
319
|
+
* @param {Connection} connection
|
|
320
|
+
* @param {string} collectionId
|
|
321
|
+
* @param {object} params
|
|
322
|
+
*/
|
|
323
|
+
constructor(connection, collectionId, params) {
|
|
324
|
+
super(connection, `/collections/${collectionId}/items`, "features", null, params);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Migrates the STAC item to the latest version.
|
|
329
|
+
*
|
|
330
|
+
* @param {object} obj
|
|
331
|
+
* @returns {Item}
|
|
332
|
+
*/
|
|
333
|
+
_createObject(obj) {
|
|
334
|
+
if (obj.stac_version) {
|
|
335
|
+
return StacMigrate.item(obj);
|
|
336
|
+
}
|
|
337
|
+
return obj;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
module.exports = {
|
|
342
|
+
Pages,
|
|
343
|
+
CollectionPages,
|
|
344
|
+
ItemPages,
|
|
345
|
+
JobPages,
|
|
346
|
+
ProcessPages,
|
|
347
|
+
ServicePages,
|
|
348
|
+
UserFilePages
|
|
349
|
+
}
|
package/src/typedefs.js
CHANGED
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
* @type {object}
|
|
48
48
|
* @property {Array.<Collection>} collections
|
|
49
49
|
* @property {Array.<Link>} links
|
|
50
|
+
* @property {Array.<string>} ["federation:missing"] A list of backends from the federation that are missing in the response data.
|
|
50
51
|
*/
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -184,6 +185,7 @@
|
|
|
184
185
|
* @property {Array.<Process>} processes
|
|
185
186
|
* @property {Array.<Link>} links
|
|
186
187
|
* @property {?Array.<string>} namespaces EXPERIMENTAL!
|
|
188
|
+
* @property {Array.<string>} ["federation:missing"] A list of backends from the federation that are missing in the response data.
|
|
187
189
|
*/
|
|
188
190
|
|
|
189
191
|
/**
|
|
@@ -193,10 +195,25 @@
|
|
|
193
195
|
* @type {object.<string, *>}
|
|
194
196
|
*/
|
|
195
197
|
|
|
198
|
+
/**
|
|
199
|
+
* An array of backends in the federation.
|
|
200
|
+
*
|
|
201
|
+
* @typedef FederationBackend
|
|
202
|
+
* @type {object}
|
|
203
|
+
* @property {string} url URL to the versioned API endpoint of the back-end.
|
|
204
|
+
* @property {string} title Name of the back-end.
|
|
205
|
+
* @property {string} description A description of the back-end and its specifics.
|
|
206
|
+
* @property {string} status Current status of the back-ends (online or offline).
|
|
207
|
+
* @property {string} last_status_check The time at which the status of the back-end was checked last, formatted as a RFC 3339 date-time.
|
|
208
|
+
* @property {string} last_successful_check If the `status` is `offline`: The time at which the back-end was checked and available the last time. Otherwise, this is equal to the property `last_status_check`. Formatted as a RFC 3339 date-time.
|
|
209
|
+
* @property {boolean} experimental Declares the back-end to be experimental.
|
|
210
|
+
* @property {boolean} deprecated Declares the back-end to be deprecated.
|
|
211
|
+
*/
|
|
212
|
+
|
|
196
213
|
/**
|
|
197
214
|
* An array, but enriched with additional details from an openEO API response.
|
|
198
215
|
*
|
|
199
|
-
* Adds
|
|
216
|
+
* Adds three properties: `links` and `federation:missing`.
|
|
200
217
|
*
|
|
201
218
|
* @typedef ResponseArray
|
|
202
219
|
* @augments Array
|
|
@@ -240,4 +257,15 @@
|
|
|
240
257
|
* @property {?UserAccountStorage} storage
|
|
241
258
|
* @property {?number} budget
|
|
242
259
|
* @property {?Array.<Link>} links
|
|
243
|
-
*/
|
|
260
|
+
*/
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* An array, but enriched with additional details from an openEO API response.
|
|
264
|
+
*
|
|
265
|
+
* Adds the property `federation:backends`.
|
|
266
|
+
*
|
|
267
|
+
* @typedef ValidationResult
|
|
268
|
+
* @augments Array
|
|
269
|
+
* @type {Array.<ApiError>}
|
|
270
|
+
* @property {Array.<string>} ["federation:backends"] The back-ends that support / do not support the process.
|
|
271
|
+
*/
|