@openeo/js-client 2.6.0 → 2.8.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/openeo.js CHANGED
@@ -1,270 +1,270 @@
1
1
  (function webpackUniversalModuleDefinition(root, factory) {
2
2
  if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("Oidc"), require("axios"));
3
+ module.exports = factory(require("axios"), require("Oidc"));
4
4
  else if(typeof define === 'function' && define.amd)
5
- define(["Oidc", "axios"], factory);
5
+ define(["axios", "Oidc"], factory);
6
6
  else {
7
- var a = typeof exports === 'object' ? factory(require("Oidc"), require("axios")) : factory(root["Oidc"], root["axios"]);
7
+ var a = typeof exports === 'object' ? factory(require("axios"), require("Oidc")) : factory(root["axios"], root["Oidc"]);
8
8
  for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
9
9
  }
10
- })(self, (__WEBPACK_EXTERNAL_MODULE__117__, __WEBPACK_EXTERNAL_MODULE__742__) => {
10
+ })(self, (__WEBPACK_EXTERNAL_MODULE__742__, __WEBPACK_EXTERNAL_MODULE__117__) => {
11
11
  return /******/ (() => { // webpackBootstrap
12
12
  /******/ var __webpack_modules__ = ({
13
13
 
14
14
  /***/ 659:
15
15
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
16
16
 
17
- const Utils = __webpack_require__(768);
18
-
19
- /**
20
- * Central registry for processes.
21
- *
22
- * @class
23
- */
24
- class ProcessRegistry {
25
-
26
- /**
27
- * Creates a new registry of all processes.
28
- *
29
- * @param {Array.<object>|ProcessRegistry} [processes=[]] - Optionally, a list of predefined processes.
30
- * @param {boolean} [addNamespace=false] - Add a namespace property to processes if set to `true`.
31
- */
32
- constructor(processes = [], addNamespace = false) {
33
- /**
34
- * List of listeners for change events.
35
- * @public
36
- */
37
- this.listeners = [];
38
- /**
39
- * Object of namespaces and processes.
40
- * @protected
41
- * @type {object.<string,object.<string,object>>}
42
- */
43
- this.processes = {};
44
- /**
45
- * Add a namespace property to processes if set to `true`.
46
- * @protected
47
- * @type {boolean}
48
- */
49
- this.addNamespace = addNamespace;
50
-
51
- // Fill process list
52
- if (processes instanceof ProcessRegistry) {
53
- for(let namespace in processes.processes) {
54
- this.addAll(processes.processes[namespace]);
55
- }
56
- }
57
- else {
58
- this.addAll(processes);
59
- }
60
- }
61
-
62
- /**
63
- * Event that is fired on changes, notifies listeners.
64
- *
65
- * @param {string} event - One of 'add', 'addAll' or 'remove'.
66
- * @param {*} data
67
- * @param {string} namespace
68
- */
69
- onChange(event, data, namespace) {
70
- for(let listener of this.listeners) {
71
- listener(event, data, namespace);
72
- }
73
- }
74
-
75
- /**
76
- * Adds a list of processes for a given namespace.
77
- *
78
- * Replaces an existing process in the given namespace if it exists.
79
- *
80
- * Fires 'addAll' event.
81
- *
82
- * @param {Array.<object>} processes Optionally, a list of processes
83
- * @param {string} [namespace="backend"] The namespace for the processes (defaults to 'backend', i.e. pre-defined processes)
84
- */
85
- addAll(processes, namespace = 'backend') {
86
- for(var i in processes) {
87
- this.add(processes[i], namespace, false);
88
- }
89
- this.onChange('addAll', processes, namespace);
90
- }
91
-
92
- /**
93
- * Adds a single process to a given namespace.
94
- *
95
- * Replaces an existing process in the given namespace if it exists.
96
- *
97
- * Fires 'add' event.
98
- *
99
- * @param {object} processes A process definition
100
- * @param {string} [namespace="backend"] The namespace for the process (defaults to 'backend', i.e. pre-defined processes)
101
- */
102
- add(process, namespace = 'backend', fireEvent = true) {
103
- if (!Utils.isObject(process)) {
104
- throw new Error("Invalid process; not an object.");
105
- }
106
- if (typeof process.id !== 'string') {
107
- throw new Error("Invalid process; no id specified.");
108
- }
109
- if (typeof namespace !== 'string') {
110
- throw new Error("Invalid namespace; not a string.");
111
- }
112
-
113
- if (!this.processes[namespace]) {
114
- this.processes[namespace] = {};
115
- }
116
- process = Object.assign(this.addNamespace ? {namespace} : {}, process);
117
- this.processes[namespace][process.id] = process;
118
- if (fireEvent) {
119
- this.onChange('add', process, namespace);
120
- }
121
- }
122
-
123
- /**
124
- * Returns the count of all processes independant of the namespaces.
125
- *
126
- * @returns {number}
127
- */
128
- count() {
129
- return Utils.size(this.all());
130
- }
131
-
132
- /**
133
- * Returns all processes as a list, independant of the namespaces.
134
- *
135
- * @returns {Array.<object>}
136
- */
137
- all() {
138
- let processes = [];
139
- for(let ns in this.processes) {
140
- processes = processes.concat(Object.values(this.processes[ns]));
141
- }
142
- return processes;
143
- }
144
-
145
- /**
146
- * Checks whether a namespace exists (i.e. at least one process for the namespace exists)
147
- *
148
- * @param {string} namespace The namespace
149
- * @returns {boolean}
150
- */
151
- hasNamespace(namespace) {
152
- if(typeof namespace !== 'string') {
153
- return false;
154
- }
155
- return Boolean(this.processes[namespace]);
156
- }
157
-
158
- /**
159
- * Returns a (sorted) list of all available namespaces.
160
- *
161
- * @returns {Array.<string>}
162
- */
163
- namespaces() {
164
- return Object.keys(this.processes).sort();
165
- }
166
-
167
- /**
168
- * Returns all processes from a specific namespace.
169
- *
170
- * Returns an empty list if the namespace is not defined.
171
- *
172
- * @param {string} namespace The namespace of the processes to return (e.g. 'backend' for pre-defined processes)
173
- * @returns {Array.<object>}
174
- */
175
- namespace(namespace) {
176
- if(typeof namespace !== 'string') {
177
- return [];
178
- }
179
- let processes = this.processes[namespace];
180
- return processes ? Object.values(processes) : [];
181
- }
182
-
183
- /**
184
- * Checks whether a process with the given ID exists in the given namespace.
185
- *
186
- * If the namespace is set to `null` (default) then it checks both user processes and backend processes.
187
- * The default namespace for pre-defined processes is `backend`.
188
- *
189
- * @param {string} id The process identifier
190
- * @param {?string} [namespace=null] The namespace of the process
191
- * @returns {boolean}
192
- */
193
- has(id, namespace = null) {
194
- return Boolean(this.get(id, namespace));
195
- }
196
-
197
- /**
198
- * Retrieve the process with the given ID fron the given namespace.
199
- *
200
- * If the namespace is set to `null` (default) then it retrieces from both (1) `user` processes and (2) `backend` processes
201
- * with preference to user processes on conflict. The default namespace for pre-defined processes is `backend`.
202
- *
203
- * @param {string} id The process identifier
204
- * @param {?string} [namespace=null] The namespace of the process
205
- * @returns {object}
206
- */
207
- get(id, namespace = null) {
208
- if (typeof id !== 'string') {
209
- return null;
210
- }
211
-
212
- // If no namespace is set, prefer the user namespace over backend namespace
213
- if (namespace === null) {
214
- return this.get(id, 'user') || this.get(id, 'backend');
215
- }
216
-
217
- if (this.processes[namespace]) {
218
- return this.processes[namespace][id] || null;
219
- }
220
- return null;
221
- }
222
-
223
- /**
224
- * Removes a single process or a complete namespace from the registry.
225
- *
226
- * If nothing is given, removes the namespace 'user'.
227
- * If only a namespace is given, removes the whole namespace.
228
- * If only a process is given, removes a process from the namespace `user`.
229
- * If both parameters are given, removes a process from the given namespace.
230
- *
231
- * Returns `true` on succes, `false` on failure.
232
- *
233
- * Fires 'remove' event.
234
- *
235
- * @param {?string} [id=null] The process identifier
236
- * @param {?string} [namespace="user"] The namespace, defaults to `user`
237
- * @returns {boolean}
238
- */
239
- remove(id = null, namespace = 'user') {
240
- if (typeof namespace !== 'string') {
241
- return false;
242
- }
243
-
244
- if (this.processes[namespace]) {
245
- if (typeof id === 'string') {
246
- if (this.processes[namespace][id]) {
247
- let process = this.processes[namespace][id];
248
- delete this.processes[namespace][id];
249
- if (Utils.size(this.processes[namespace]) === 0) {
250
- delete this.processes[namespace];
251
- }
252
- this.onChange('remove', process, namespace);
253
- return true;
254
- }
255
- }
256
- else {
257
- delete this.processes[namespace];
258
- this.onChange('remove', null, namespace);
259
- return true;
260
- }
261
- }
262
-
263
- return false;
264
- }
265
-
266
- }
267
-
17
+ const Utils = __webpack_require__(768);
18
+
19
+ /**
20
+ * Central registry for processes.
21
+ *
22
+ * @class
23
+ */
24
+ class ProcessRegistry {
25
+
26
+ /**
27
+ * Creates a new registry of all processes.
28
+ *
29
+ * @param {Array.<object>|ProcessRegistry} [processes=[]] - Optionally, a list of predefined processes.
30
+ * @param {boolean} [addNamespace=false] - Add a namespace property to processes if set to `true`.
31
+ */
32
+ constructor(processes = [], addNamespace = false) {
33
+ /**
34
+ * List of listeners for change events.
35
+ * @public
36
+ */
37
+ this.listeners = [];
38
+ /**
39
+ * Object of namespaces and processes.
40
+ * @protected
41
+ * @type {object.<string,object.<string,object>>}
42
+ */
43
+ this.processes = {};
44
+ /**
45
+ * Add a namespace property to processes if set to `true`.
46
+ * @protected
47
+ * @type {boolean}
48
+ */
49
+ this.addNamespace = addNamespace;
50
+
51
+ // Fill process list
52
+ if (processes instanceof ProcessRegistry) {
53
+ for(let namespace in processes.processes) {
54
+ this.addAll(processes.processes[namespace]);
55
+ }
56
+ }
57
+ else {
58
+ this.addAll(processes);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Event that is fired on changes, notifies listeners.
64
+ *
65
+ * @param {string} event - One of 'add', 'addAll' or 'remove'.
66
+ * @param {*} data
67
+ * @param {string} namespace
68
+ */
69
+ onChange(event, data, namespace) {
70
+ for(let listener of this.listeners) {
71
+ listener(event, data, namespace);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Adds a list of processes for a given namespace.
77
+ *
78
+ * Replaces an existing process in the given namespace if it exists.
79
+ *
80
+ * Fires 'addAll' event.
81
+ *
82
+ * @param {Array.<object>} processes Optionally, a list of processes
83
+ * @param {string} [namespace="backend"] The namespace for the processes (defaults to 'backend', i.e. pre-defined processes)
84
+ */
85
+ addAll(processes, namespace = 'backend') {
86
+ for(var i in processes) {
87
+ this.add(processes[i], namespace, false);
88
+ }
89
+ this.onChange('addAll', processes, namespace);
90
+ }
91
+
92
+ /**
93
+ * Adds a single process to a given namespace.
94
+ *
95
+ * Replaces an existing process in the given namespace if it exists.
96
+ *
97
+ * Fires 'add' event.
98
+ *
99
+ * @param {object} processes A process definition
100
+ * @param {string} [namespace="backend"] The namespace for the process (defaults to 'backend', i.e. pre-defined processes)
101
+ */
102
+ add(process, namespace = 'backend', fireEvent = true) {
103
+ if (!Utils.isObject(process)) {
104
+ throw new Error("Invalid process; not an object.");
105
+ }
106
+ if (typeof process.id !== 'string') {
107
+ throw new Error("Invalid process; no id specified.");
108
+ }
109
+ if (typeof namespace !== 'string') {
110
+ throw new Error("Invalid namespace; not a string.");
111
+ }
112
+
113
+ if (!this.processes[namespace]) {
114
+ this.processes[namespace] = {};
115
+ }
116
+ process = Object.assign(this.addNamespace ? {namespace} : {}, process);
117
+ this.processes[namespace][process.id] = process;
118
+ if (fireEvent) {
119
+ this.onChange('add', process, namespace);
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Returns the count of all processes independant of the namespaces.
125
+ *
126
+ * @returns {number}
127
+ */
128
+ count() {
129
+ return Utils.size(this.all());
130
+ }
131
+
132
+ /**
133
+ * Returns all processes as a list, independant of the namespaces.
134
+ *
135
+ * @returns {Array.<object>}
136
+ */
137
+ all() {
138
+ let processes = [];
139
+ for(let ns in this.processes) {
140
+ processes = processes.concat(Object.values(this.processes[ns]));
141
+ }
142
+ return processes;
143
+ }
144
+
145
+ /**
146
+ * Checks whether a namespace exists (i.e. at least one process for the namespace exists)
147
+ *
148
+ * @param {string} namespace The namespace
149
+ * @returns {boolean}
150
+ */
151
+ hasNamespace(namespace) {
152
+ if(typeof namespace !== 'string') {
153
+ return false;
154
+ }
155
+ return Boolean(this.processes[namespace]);
156
+ }
157
+
158
+ /**
159
+ * Returns a (sorted) list of all available namespaces.
160
+ *
161
+ * @returns {Array.<string>}
162
+ */
163
+ namespaces() {
164
+ return Object.keys(this.processes).sort();
165
+ }
166
+
167
+ /**
168
+ * Returns all processes from a specific namespace.
169
+ *
170
+ * Returns an empty list if the namespace is not defined.
171
+ *
172
+ * @param {string} namespace The namespace of the processes to return (e.g. 'backend' for pre-defined processes)
173
+ * @returns {Array.<object>}
174
+ */
175
+ namespace(namespace) {
176
+ if(typeof namespace !== 'string') {
177
+ return [];
178
+ }
179
+ let processes = this.processes[namespace];
180
+ return processes ? Object.values(processes) : [];
181
+ }
182
+
183
+ /**
184
+ * Checks whether a process with the given ID exists in the given namespace.
185
+ *
186
+ * If the namespace is set to `null` (default) then it checks both user processes and backend processes.
187
+ * The default namespace for pre-defined processes is `backend`.
188
+ *
189
+ * @param {string} id The process identifier
190
+ * @param {?string} [namespace=null] The namespace of the process
191
+ * @returns {boolean}
192
+ */
193
+ has(id, namespace = null) {
194
+ return Boolean(this.get(id, namespace));
195
+ }
196
+
197
+ /**
198
+ * Retrieve the process with the given ID fron the given namespace.
199
+ *
200
+ * If the namespace is set to `null` (default) then it retrieces from both (1) `user` processes and (2) `backend` processes
201
+ * with preference to user processes on conflict. The default namespace for pre-defined processes is `backend`.
202
+ *
203
+ * @param {string} id The process identifier
204
+ * @param {?string} [namespace=null] The namespace of the process
205
+ * @returns {object}
206
+ */
207
+ get(id, namespace = null) {
208
+ if (typeof id !== 'string') {
209
+ return null;
210
+ }
211
+
212
+ // If no namespace is set, prefer the user namespace over backend namespace
213
+ if (namespace === null) {
214
+ return this.get(id, 'user') || this.get(id, 'backend');
215
+ }
216
+
217
+ if (this.processes[namespace]) {
218
+ return this.processes[namespace][id] || null;
219
+ }
220
+ return null;
221
+ }
222
+
223
+ /**
224
+ * Removes a single process or a complete namespace from the registry.
225
+ *
226
+ * If nothing is given, removes the namespace 'user'.
227
+ * If only a namespace is given, removes the whole namespace.
228
+ * If only a process is given, removes a process from the namespace `user`.
229
+ * If both parameters are given, removes a process from the given namespace.
230
+ *
231
+ * Returns `true` on succes, `false` on failure.
232
+ *
233
+ * Fires 'remove' event.
234
+ *
235
+ * @param {?string} [id=null] The process identifier
236
+ * @param {?string} [namespace="user"] The namespace, defaults to `user`
237
+ * @returns {boolean}
238
+ */
239
+ remove(id = null, namespace = 'user') {
240
+ if (typeof namespace !== 'string') {
241
+ return false;
242
+ }
243
+
244
+ if (this.processes[namespace]) {
245
+ if (typeof id === 'string') {
246
+ if (this.processes[namespace][id]) {
247
+ let process = this.processes[namespace][id];
248
+ delete this.processes[namespace][id];
249
+ if (Utils.size(this.processes[namespace]) === 0) {
250
+ delete this.processes[namespace];
251
+ }
252
+ this.onChange('remove', process, namespace);
253
+ return true;
254
+ }
255
+ }
256
+ else {
257
+ delete this.processes[namespace];
258
+ this.onChange('remove', null, namespace);
259
+ return true;
260
+ }
261
+ }
262
+
263
+ return false;
264
+ }
265
+
266
+ }
267
+
268
268
  module.exports = ProcessRegistry;
269
269
 
270
270
  /***/ }),
@@ -272,206 +272,206 @@ module.exports = ProcessRegistry;
272
272
  /***/ 779:
273
273
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
274
274
 
275
- const Utils = __webpack_require__(768);
276
-
277
- /**
278
- * Utilities to parse process specs and JSON schemas.
279
- *
280
- * @class
281
- */
282
- class ProcessUtils {
283
-
284
- /**
285
- * From a "complex" JSON Schema with allOf/anyOf/oneOf, make separate schemas.
286
- *
287
- * So afterwards each schema has it's own array entry.
288
- * It merges allOf, resolves anyOf/oneOf into separate schemas.
289
- * May also split the JSON Schema type arrays into separate entries by setting `splitTypes` to `true`.
290
- *
291
- * @param {object|array} schemas - The JSON Schema(s) to convert
292
- * @returns {array}
293
- */
294
- static normalizeJsonSchema(schemas, splitTypes = false) {
295
- // Make schemas always an array
296
- if (Utils.isObject(schemas)) {
297
- schemas = [schemas];
298
- }
299
- else if (Array.isArray(schemas)) {
300
- schemas = schemas;
301
- }
302
- else {
303
- schemas = [];
304
- }
305
-
306
- // Merge allOf, resolve anyOf/oneOf into separate schemas
307
- let normalized = [];
308
- for(let schema of schemas) {
309
- if (Array.isArray(schema.allOf)) {
310
- normalized.push(Object.assign({}, ...schema.allOf));
311
- }
312
- else if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
313
- let copy = Utils.omitFromObject(schema, ['oneOf', 'anyOf']);
314
- let subSchemas = schema.oneOf || schema.anyOf;
315
- for(let subSchema of subSchemas) {
316
- normalized.push(Object.assign({}, copy, subSchema));
317
- }
318
- }
319
- else {
320
- normalized.push(schema);
321
- }
322
- }
323
-
324
- if (!splitTypes) {
325
- return normalized;
326
- }
327
-
328
- // Split type field into separate schemas
329
- schemas = [];
330
- for(let schema of normalized) {
331
- if (Array.isArray(schema.type)) {
332
- /* jshint ignore:start */
333
- schemas = schemas.concat(schema.type.map(type => Object.assign({}, schema, {type: type})));
334
- /* jshint ignore:end */
335
- }
336
- else {
337
- schemas.push(schema);
338
- }
339
- }
340
-
341
- return schemas;
342
- }
343
-
344
- /**
345
- * Returns the callback parameters for a given process parameter.
346
- *
347
- * @param {object} processParameter - The process parameter spec to parse.
348
- * @returns {array}
349
- * @throws {Error}
350
- */
351
- static getCallbackParameters(processParameter, keyPath = []) {
352
- if (!Utils.isObject(processParameter) || !processParameter.schema) {
353
- return [];
354
- }
355
-
356
- let schemas = ProcessUtils.normalizeJsonSchema(processParameter.schema);
357
- let key;
358
- while(key = keyPath.shift()) { // jshint ignore:line
359
- schemas = schemas.map(schema => ProcessUtils.normalizeJsonSchema(ProcessUtils.getElementJsonSchema(schema, key))); // jshint ignore:line
360
- schemas = schemas.concat(...schemas);
361
- }
362
-
363
-
364
- let cbParams = [];
365
- for(let schema of schemas) {
366
- let params = null;
367
- if (Array.isArray(schema.parameters)) { // For "normal" callbacks
368
- params = schema.parameters;
369
- }
370
- else if (Utils.isObject(schema.additionalProperties) && Array.isArray(schema.additionalProperties.parameters)) {
371
- params = schema.additionalProperties.parameters; // Used for metadata-filter
372
- }
373
- if (Array.isArray(params)) {
374
- if (cbParams.length > 0 && !Utils.equals(cbParams, params)) {
375
- throw new Error("Multiple schemas with different callback parameters found.");
376
- }
377
- cbParams = params;
378
- }
379
- }
380
-
381
- return cbParams;
382
- }
383
-
384
- /**
385
- * Returns the callback parameters for a given process parameter from a full process spec.
386
- *
387
- * @param {object} process - The process to parse.
388
- * @param {string} parameterName - The name of the parameter to get the callback parameters for.
389
- * @returns {array}
390
- * @throws {Error}
391
- */
392
- static getCallbackParametersForProcess(process, parameterName, path = []) {
393
- if (!Utils.isObject(process) || !Array.isArray(process.parameters)) {
394
- return [];
395
- }
396
-
397
- let param = process.parameters.find(p => p.name === parameterName);
398
- return ProcessUtils.getCallbackParameters(param, path);
399
- }
400
-
401
- /**
402
- * Returns *all* the native JSON data types allowed for the schema.
403
- *
404
- * @param {object} schema
405
- * @param {boolean} anyIsEmpty
406
- * @returns {array}
407
- */
408
- static getNativeTypesForJsonSchema(schema, anyIsEmpty = false) {
409
- if (Utils.isObject(schema) && Array.isArray(schema.type)) {
410
- // Remove duplicate and invalid types
411
- let validTypes = Utils.unique(schema.type).filter(type => ProcessUtils.JSON_SCHEMA_TYPES.includes(type));
412
- if (validTypes.length > 0 && validTypes.length < ProcessUtils.JSON_SCHEMA_TYPES.length) {
413
- return validTypes;
414
- }
415
- else {
416
- return anyIsEmpty ? [] : ProcessUtils.JSON_SCHEMA_TYPES;
417
- }
418
- }
419
- else if (Utils.isObject(schema) && typeof schema.type === 'string' && ProcessUtils.JSON_SCHEMA_TYPES.includes(schema.type)) {
420
- return [schema.type];
421
- }
422
- else {
423
- return anyIsEmpty ? [] : ProcessUtils.JSON_SCHEMA_TYPES;
424
- }
425
- }
426
-
427
- /**
428
- * Returns the schema for a property of an object or an element of an array.
429
- *
430
- * If you want to retrieve the schema for a specific key, use the parameter `key`.
431
- *
432
- * @param {object} schema - The JSON schema to parse.
433
- * @param {string|integer|null} key - If you want to retrieve the schema for a specific key, otherwise null.
434
- * @returns {object} - JSON Schema
435
- */
436
- static getElementJsonSchema(schema, key = null) {
437
- let types = ProcessUtils.getNativeTypesForJsonSchema(schema);
438
- if (Utils.isObject(schema) && types.includes('array') && typeof key !== 'string') {
439
- if (Utils.isObject(schema.items)) {
440
- // Array with one schema for all items: https://json-schema.org/understanding-json-schema/reference/array.html#id5
441
- return schema.items;
442
- }
443
- else if (Array.isArray(schema.items)) {
444
- // Tuple validation: https://json-schema.org/understanding-json-schema/reference/array.html#id6
445
- if (key !== null && Utils.isObject(schema.items[key])) {
446
- return schema.items[key];
447
- }
448
- else if (Utils.isObject(schema.additionalItems)) {
449
- return schema.additionalItems;
450
- }
451
- }
452
- }
453
- if (Utils.isObject(schema) && types.includes('object')) {
454
- if (key !== null && Utils.isObject(schema.properties) && Utils.isObject(schema.properties[key])) {
455
- return schema.properties[key];
456
- }
457
- else if (Utils.isObject(schema.additionalProperties)) {
458
- return schema.additionalProperties;
459
- }
460
- // ToDo: No support for patternProperties yet
461
- }
462
-
463
- return {};
464
- }
465
-
466
- }
467
-
468
- /**
469
- * A list of all allowed JSON Schema type values.
470
- *
471
- * @type {array}
472
- */
473
- ProcessUtils.JSON_SCHEMA_TYPES = ['string', 'number', 'integer', 'boolean', 'array', 'object', 'null'];
474
-
275
+ const Utils = __webpack_require__(768);
276
+
277
+ /**
278
+ * Utilities to parse process specs and JSON schemas.
279
+ *
280
+ * @class
281
+ */
282
+ class ProcessUtils {
283
+
284
+ /**
285
+ * From a "complex" JSON Schema with allOf/anyOf/oneOf, make separate schemas.
286
+ *
287
+ * So afterwards each schema has it's own array entry.
288
+ * It merges allOf, resolves anyOf/oneOf into separate schemas.
289
+ * May also split the JSON Schema type arrays into separate entries by setting `splitTypes` to `true`.
290
+ *
291
+ * @param {object|array} schemas - The JSON Schema(s) to convert
292
+ * @returns {array}
293
+ */
294
+ static normalizeJsonSchema(schemas, splitTypes = false) {
295
+ // Make schemas always an array
296
+ if (Utils.isObject(schemas)) {
297
+ schemas = [schemas];
298
+ }
299
+ else if (Array.isArray(schemas)) {
300
+ schemas = schemas;
301
+ }
302
+ else {
303
+ schemas = [];
304
+ }
305
+
306
+ // Merge allOf, resolve anyOf/oneOf into separate schemas
307
+ let normalized = [];
308
+ for(let schema of schemas) {
309
+ if (Array.isArray(schema.allOf)) {
310
+ normalized.push(Object.assign({}, ...schema.allOf));
311
+ }
312
+ else if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
313
+ let copy = Utils.omitFromObject(schema, ['oneOf', 'anyOf']);
314
+ let subSchemas = schema.oneOf || schema.anyOf;
315
+ for(let subSchema of subSchemas) {
316
+ normalized.push(Object.assign({}, copy, subSchema));
317
+ }
318
+ }
319
+ else {
320
+ normalized.push(schema);
321
+ }
322
+ }
323
+
324
+ if (!splitTypes) {
325
+ return normalized;
326
+ }
327
+
328
+ // Split type field into separate schemas
329
+ schemas = [];
330
+ for(let schema of normalized) {
331
+ if (Array.isArray(schema.type)) {
332
+ /* jshint ignore:start */
333
+ schemas = schemas.concat(schema.type.map(type => Object.assign({}, schema, {type: type})));
334
+ /* jshint ignore:end */
335
+ }
336
+ else {
337
+ schemas.push(schema);
338
+ }
339
+ }
340
+
341
+ return schemas;
342
+ }
343
+
344
+ /**
345
+ * Returns the callback parameters for a given process parameter.
346
+ *
347
+ * @param {object} processParameter - The process parameter spec to parse.
348
+ * @returns {array}
349
+ * @throws {Error}
350
+ */
351
+ static getCallbackParameters(processParameter, keyPath = []) {
352
+ if (!Utils.isObject(processParameter) || !processParameter.schema) {
353
+ return [];
354
+ }
355
+
356
+ let schemas = ProcessUtils.normalizeJsonSchema(processParameter.schema);
357
+ let key;
358
+ while(key = keyPath.shift()) { // jshint ignore:line
359
+ schemas = schemas.map(schema => ProcessUtils.normalizeJsonSchema(ProcessUtils.getElementJsonSchema(schema, key))); // jshint ignore:line
360
+ schemas = schemas.concat(...schemas);
361
+ }
362
+
363
+
364
+ let cbParams = [];
365
+ for(let schema of schemas) {
366
+ let params = null;
367
+ if (Array.isArray(schema.parameters)) { // For "normal" callbacks
368
+ params = schema.parameters;
369
+ }
370
+ else if (Utils.isObject(schema.additionalProperties) && Array.isArray(schema.additionalProperties.parameters)) {
371
+ params = schema.additionalProperties.parameters; // Used for metadata-filter
372
+ }
373
+ if (Array.isArray(params)) {
374
+ if (cbParams.length > 0 && !Utils.equals(cbParams, params)) {
375
+ throw new Error("Multiple schemas with different callback parameters found.");
376
+ }
377
+ cbParams = params;
378
+ }
379
+ }
380
+
381
+ return cbParams;
382
+ }
383
+
384
+ /**
385
+ * Returns the callback parameters for a given process parameter from a full process spec.
386
+ *
387
+ * @param {object} process - The process to parse.
388
+ * @param {string} parameterName - The name of the parameter to get the callback parameters for.
389
+ * @returns {array}
390
+ * @throws {Error}
391
+ */
392
+ static getCallbackParametersForProcess(process, parameterName, path = []) {
393
+ if (!Utils.isObject(process) || !Array.isArray(process.parameters)) {
394
+ return [];
395
+ }
396
+
397
+ let param = process.parameters.find(p => p.name === parameterName);
398
+ return ProcessUtils.getCallbackParameters(param, path);
399
+ }
400
+
401
+ /**
402
+ * Returns *all* the native JSON data types allowed for the schema.
403
+ *
404
+ * @param {object} schema
405
+ * @param {boolean} anyIsEmpty
406
+ * @returns {array}
407
+ */
408
+ static getNativeTypesForJsonSchema(schema, anyIsEmpty = false) {
409
+ if (Utils.isObject(schema) && Array.isArray(schema.type)) {
410
+ // Remove duplicate and invalid types
411
+ let validTypes = Utils.unique(schema.type).filter(type => ProcessUtils.JSON_SCHEMA_TYPES.includes(type));
412
+ if (validTypes.length > 0 && validTypes.length < ProcessUtils.JSON_SCHEMA_TYPES.length) {
413
+ return validTypes;
414
+ }
415
+ else {
416
+ return anyIsEmpty ? [] : ProcessUtils.JSON_SCHEMA_TYPES;
417
+ }
418
+ }
419
+ else if (Utils.isObject(schema) && typeof schema.type === 'string' && ProcessUtils.JSON_SCHEMA_TYPES.includes(schema.type)) {
420
+ return [schema.type];
421
+ }
422
+ else {
423
+ return anyIsEmpty ? [] : ProcessUtils.JSON_SCHEMA_TYPES;
424
+ }
425
+ }
426
+
427
+ /**
428
+ * Returns the schema for a property of an object or an element of an array.
429
+ *
430
+ * If you want to retrieve the schema for a specific key, use the parameter `key`.
431
+ *
432
+ * @param {object} schema - The JSON schema to parse.
433
+ * @param {string|integer|null} key - If you want to retrieve the schema for a specific key, otherwise null.
434
+ * @returns {object} - JSON Schema
435
+ */
436
+ static getElementJsonSchema(schema, key = null) {
437
+ let types = ProcessUtils.getNativeTypesForJsonSchema(schema);
438
+ if (Utils.isObject(schema) && types.includes('array') && typeof key !== 'string') {
439
+ if (Utils.isObject(schema.items)) {
440
+ // Array with one schema for all items: https://json-schema.org/understanding-json-schema/reference/array.html#id5
441
+ return schema.items;
442
+ }
443
+ else if (Array.isArray(schema.items)) {
444
+ // Tuple validation: https://json-schema.org/understanding-json-schema/reference/array.html#id6
445
+ if (key !== null && Utils.isObject(schema.items[key])) {
446
+ return schema.items[key];
447
+ }
448
+ else if (Utils.isObject(schema.additionalItems)) {
449
+ return schema.additionalItems;
450
+ }
451
+ }
452
+ }
453
+ if (Utils.isObject(schema) && types.includes('object')) {
454
+ if (key !== null && Utils.isObject(schema.properties) && Utils.isObject(schema.properties[key])) {
455
+ return schema.properties[key];
456
+ }
457
+ else if (Utils.isObject(schema.additionalProperties)) {
458
+ return schema.additionalProperties;
459
+ }
460
+ // ToDo: No support for patternProperties yet
461
+ }
462
+
463
+ return {};
464
+ }
465
+
466
+ }
467
+
468
+ /**
469
+ * A list of all allowed JSON Schema type values.
470
+ *
471
+ * @type {array}
472
+ */
473
+ ProcessUtils.JSON_SCHEMA_TYPES = ['string', 'number', 'integer', 'boolean', 'array', 'object', 'null'];
474
+
475
475
  module.exports = ProcessUtils;
476
476
 
477
477
  /***/ }),
@@ -479,327 +479,327 @@ module.exports = ProcessUtils;
479
479
  /***/ 768:
480
480
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
481
481
 
482
- var equal = __webpack_require__(252);
483
-
484
- /**
485
- * General utilities
486
- *
487
- * @class
488
- */
489
- class Utils {
490
-
491
- /**
492
- * Checks whether a variable is a real object or not.
493
- *
494
- * This is a more strict version of `typeof x === 'object'` as this example would also succeeds for arrays and `null`.
495
- * This function only returns `true` for real objects and not for arrays, `null` or any other data types.
496
- *
497
- * @param {*} obj - A variable to check.
498
- * @returns {boolean} - `true` is the given variable is an object, `false` otherwise.
499
- */
500
- static isObject(obj) {
501
- return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
502
- }
503
-
504
- /**
505
- * Checks whether a variable is a string and contains at least one character.
506
- *
507
- * @param {*} string - A variable to check.
508
- * @returns {boolean} - `true` is the given variable is an string with length > 0, `false` otherwise.
509
- */
510
- static hasText(string) {
511
- return (typeof string === 'string' && string.length > 0);
512
- }
513
-
514
- /**
515
- * Performs a deep comparison between two values to determine if they are equivalent.
516
- *
517
- * @param {*} x - The value to compare.
518
- * @param {*} y - The other value to compare.
519
- * @returns {boolean} - Returns true if the values are equivalent, else false.
520
- */
521
- static equals(x, y) {
522
- return equal(x, y);
523
- }
524
-
525
- /**
526
- * Creates an object composed of the picked object properties.
527
- *
528
- * Returns a shallow copy!
529
- *
530
- * @param {object} obj - The source object.
531
- * @param {string|array} toPick - The properties to pick.
532
- * @returns {object}
533
- */
534
- static pickFromObject(obj, toPick) {
535
- obj = Object(obj);
536
- if (typeof toPick === 'string') {
537
- toPick = [toPick];
538
- }
539
- const copy = {};
540
- toPick.forEach(key => copy[key] = obj[key]);
541
- return copy;
542
- }
543
-
544
- /**
545
- * This method creates an object composed of the own and inherited enumerable property paths of object that are not omitted.
546
- *
547
- * Returns a shallow copy!
548
- *
549
- * @param {object} obj - The source object.
550
- * @param {string|array} toOmit - The properties to omit.
551
- * @returns {object}
552
- */
553
- static omitFromObject(obj, toOmit) {
554
- obj = Object(obj);
555
- if (typeof toOmit === 'string') {
556
- toOmit = [toOmit];
557
- }
558
- var copy = Object.assign({}, obj);
559
- for(let key of toOmit) {
560
- delete copy[key];
561
- }
562
- return copy;
563
- }
564
-
565
- /**
566
- * Creates an array of values by running each property of `object` thru function.
567
- *
568
- * The function is invoked with three arguments: (value, key, object).
569
- *
570
- * @param {object} obj
571
- * @param {function} func
572
- * @returns {object}
573
- */
574
- static mapObject(obj, func) {
575
- // Taken from lodash, see https://github.com/lodash/lodash/blob/master/mapObject.js
576
- const props = Object.keys(obj);
577
- const result = new Array(props.length);
578
- props.forEach((key, index) => {
579
- result[index] = func(obj[key], key, obj);
580
- });
581
- return result;
582
- }
583
-
584
- /**
585
- * Creates an object with the same keys as object and values generated by running each own enumerable string keyed property of object thru the function.
586
- *
587
- * The function is invoked with three arguments: (value, key, object).
588
- *
589
- * @param {object} obj
590
- * @param {function} func
591
- * @returns {object}
592
- */
593
- static mapObjectValues(obj, func) {
594
- // Taken from lodash, see https://github.com/lodash/lodash/blob/master/mapValue.js
595
- obj = Object(obj);
596
- const result = {};
597
- Object.keys(obj).forEach((key) => {
598
- result[key] = func(obj[key], key, obj);
599
- });
600
- return result;
601
- }
602
-
603
- /**
604
- * Creates a duplicate-free version of an array.
605
- *
606
- * If useEquals is set to true, uses the `Utils.equals` function for comparison instead of
607
- * the JS === operator. Thus, if the array contains objects, you likely want to set
608
- * `useEquals` to `true`.
609
- *
610
- * @param {array} array
611
- * @param {boolean} useEquals
612
- * @returns {array}
613
- */
614
- static unique(array, useEquals = false) {
615
- if (useEquals) {
616
- return array.filter((s1, pos, arr) => arr.findIndex(s2 => Utils.equals(s1, s2)) === pos);
617
- }
618
- else {
619
- return [...new Set(array)];
620
- }
621
- }
622
-
623
- /**
624
- * Computes the size of an array (number of array elements) or object (number of key-value-pairs).
625
- *
626
- * Returns 0 for all other data types.
627
- *
628
- * @param {*} obj
629
- * @returns {integer}
630
- */
631
- static size(obj) {
632
- if (typeof obj === 'object' && obj !== null) {
633
- if (Array.isArray(obj)) {
634
- return obj.length;
635
- }
636
- else {
637
- return Object.keys(obj).length;
638
- }
639
- }
640
- return 0;
641
- }
642
-
643
- /**
644
- * Checks whether a variable is numeric.
645
- *
646
- * Numeric is every string with numeric data or a number, excluding NaN and finite numbers.
647
- *
648
- * @param {*} n - A variable to check.
649
- * @returns {boolean} - `true` is the given variable is numeric, `false` otherwise.
650
- */
651
- static isNumeric(n) {
652
- return !isNaN(parseFloat(n)) && isFinite(n);
653
- }
654
-
655
- /**
656
- * Deep clone for JSON-compatible data.
657
- *
658
- * @param {*} x - The data to clone.
659
- * @returns {*} - The cloned data.
660
- */
661
- static deepClone(x) {
662
- return JSON.parse(JSON.stringify(x));
663
- }
664
-
665
- /**
666
- * Normalize a URL (mostly handling leading and trailing slashes).
667
- *
668
- * @static
669
- * @param {string} baseUrl - The URL to normalize
670
- * @param {string} path - An optional path to add to the URL
671
- * @returns {string} Normalized URL.
672
- */
673
- static normalizeUrl(baseUrl, path = null) {
674
- let url = baseUrl.replace(/\/$/, ""); // Remove trailing slash from base URL
675
- if (typeof path === 'string') {
676
- if (path.substr(0, 1) !== '/') {
677
- path = '/' + path; // Add leading slash to path
678
- }
679
- url = url + path.replace(/\/$/, ""); // Remove trailing slash from path
680
- }
681
- return url;
682
- }
683
-
684
- /**
685
- * Replaces placeholders in this format: `{var}`.
686
- *
687
- * This can be used for the placeholders/variables in the openEO API's errors.json file.
688
- *
689
- * @param {string} message - The string to replace the placeholders in.
690
- * @param {object} variables - A map with the placeholder names as keys and the replacement value as value.
691
- */
692
- static replacePlaceholders(message, variables = {}) {
693
- if (typeof message === 'string' && Utils.isObject(variables)) {
694
- for(var placeholder in variables) {
695
- let vars = variables[placeholder];
696
- message = message.replace('{' + placeholder + '}', Array.isArray(vars) ? vars.join("; ") : vars);
697
- }
698
- }
699
- return message;
700
- }
701
-
702
- /**
703
- * Compares two strings case-insensitive, including natural ordering for numbers.
704
- *
705
- * @param {string} a
706
- * @param {string} b
707
- * @returns {integer} Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
708
- */
709
- static compareStringCaseInsensitive(a, b) {
710
- if (typeof a !== 'string') {
711
- a = String(a);
712
- }
713
- if (typeof b !== 'string') {
714
- b = String(b);
715
- }
716
- return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'});
717
- }
718
-
719
- /**
720
- * Tries to make a string more readable by capitalizing it.
721
- * Only applies to words with more than two characters.
722
- *
723
- * Supports converting from:
724
- * - Snake Case (abc_def => Abc Def)
725
- * - Kebab Case (abc-def => Abc Def)
726
- * - Camel Case (abcDef => Abc Def)
727
- *
728
- * Doesn't capitalize if the words are not in any of the casing formats above.
729
- *
730
- * @param {*} strings - String(s) to make readable
731
- * @param {string} arraySep - String to separate array elements with
732
- * @returns {string}
733
- */
734
- static prettifyString(strings, arraySep = '; ') {
735
- if (!Array.isArray(strings)) {
736
- strings = [String(strings)];
737
- }
738
- strings = strings.map(str => {
739
- if (str.length >= 3) {
740
- const replacer = (_,a,b) => a + ' ' + b.toUpperCase();
741
- if (str.includes('_')) {
742
- // Snake case converter
743
- str = str.replace(/([a-zA-Z\d])_([a-zA-Z\d])/g, replacer);
744
- }
745
- else if (str.includes('-')) {
746
- // Kebab case converter
747
- str = str.replace(/([a-zA-Z\d])-([a-zA-Z\d])/g, replacer);
748
- }
749
- else {
750
- // Camelcase converter
751
- str = str.replace(/([a-z])([A-Z])/g, replacer);
752
- }
753
- // Uppercase the first letter in the first word, too.
754
- return str.charAt(0).toUpperCase() + str.substr(1);
755
- }
756
- return str;
757
- });
758
- return strings.join(arraySep);
759
- }
760
-
761
- /**
762
- * Makes link lists from the openEO API more user-friendly.
763
- *
764
- * Supports:
765
- * - Set a reasonable title, if not available. Make title more readable.
766
- * - Sorting by title (see `sort` parameter)
767
- * - Removing given relation types (`rel` property, see `ignoreRel` parameter)
768
- *
769
- * @param {array} linkList - List of links
770
- * @param {boolean} sort - Enable/Disable sorting by title. Enabled (true) by default.
771
- * @param {array} ignoreRel - A list of rel types to remove. By default, removes the self links (rel type = `self`).
772
- * @returns {array}
773
- */
774
- static friendlyLinks(linkList, sort = true, ignoreRel = ['self']) {
775
- let links = [];
776
- if (!Array.isArray(linkList)) {
777
- return links;
778
- }
779
-
780
- for(let link of linkList) {
781
- link = Object.assign({}, link); // Make sure to work on a copy
782
- if (typeof link.rel === 'string' && ignoreRel.includes(link.rel.toLowerCase())) {
783
- continue;
784
- }
785
- if (typeof link.title !== 'string' || link.title.length === 0) {
786
- if (typeof link.rel === 'string' && link.rel.length > 1) {
787
- link.title = Utils.prettifyString(link.rel);
788
- }
789
- else {
790
- link.title = link.href.replace(/^https?:\/\/(www.)?/i, '').replace(/\/$/i, '');
791
- }
792
- }
793
- links.push(link);
794
- }
795
- if (sort) {
796
- links.sort((a, b) => Utils.compareStringCaseInsensitive(a.title, b.title));
797
- }
798
- return links;
799
- }
800
-
801
- }
802
-
482
+ var equal = __webpack_require__(252);
483
+
484
+ /**
485
+ * General utilities
486
+ *
487
+ * @class
488
+ */
489
+ class Utils {
490
+
491
+ /**
492
+ * Checks whether a variable is a real object or not.
493
+ *
494
+ * This is a more strict version of `typeof x === 'object'` as this example would also succeeds for arrays and `null`.
495
+ * This function only returns `true` for real objects and not for arrays, `null` or any other data types.
496
+ *
497
+ * @param {*} obj - A variable to check.
498
+ * @returns {boolean} - `true` is the given variable is an object, `false` otherwise.
499
+ */
500
+ static isObject(obj) {
501
+ return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
502
+ }
503
+
504
+ /**
505
+ * Checks whether a variable is a string and contains at least one character.
506
+ *
507
+ * @param {*} string - A variable to check.
508
+ * @returns {boolean} - `true` is the given variable is an string with length > 0, `false` otherwise.
509
+ */
510
+ static hasText(string) {
511
+ return (typeof string === 'string' && string.length > 0);
512
+ }
513
+
514
+ /**
515
+ * Performs a deep comparison between two values to determine if they are equivalent.
516
+ *
517
+ * @param {*} x - The value to compare.
518
+ * @param {*} y - The other value to compare.
519
+ * @returns {boolean} - Returns true if the values are equivalent, else false.
520
+ */
521
+ static equals(x, y) {
522
+ return equal(x, y);
523
+ }
524
+
525
+ /**
526
+ * Creates an object composed of the picked object properties.
527
+ *
528
+ * Returns a shallow copy!
529
+ *
530
+ * @param {object} obj - The source object.
531
+ * @param {string|array} toPick - The properties to pick.
532
+ * @returns {object}
533
+ */
534
+ static pickFromObject(obj, toPick) {
535
+ obj = Object(obj);
536
+ if (typeof toPick === 'string') {
537
+ toPick = [toPick];
538
+ }
539
+ const copy = {};
540
+ toPick.forEach(key => copy[key] = obj[key]);
541
+ return copy;
542
+ }
543
+
544
+ /**
545
+ * This method creates an object composed of the own and inherited enumerable property paths of object that are not omitted.
546
+ *
547
+ * Returns a shallow copy!
548
+ *
549
+ * @param {object} obj - The source object.
550
+ * @param {string|array} toOmit - The properties to omit.
551
+ * @returns {object}
552
+ */
553
+ static omitFromObject(obj, toOmit) {
554
+ obj = Object(obj);
555
+ if (typeof toOmit === 'string') {
556
+ toOmit = [toOmit];
557
+ }
558
+ var copy = Object.assign({}, obj);
559
+ for(let key of toOmit) {
560
+ delete copy[key];
561
+ }
562
+ return copy;
563
+ }
564
+
565
+ /**
566
+ * Creates an array of values by running each property of `object` thru function.
567
+ *
568
+ * The function is invoked with three arguments: (value, key, object).
569
+ *
570
+ * @param {object} obj
571
+ * @param {function} func
572
+ * @returns {object}
573
+ */
574
+ static mapObject(obj, func) {
575
+ // Taken from lodash, see https://github.com/lodash/lodash/blob/master/mapObject.js
576
+ const props = Object.keys(obj);
577
+ const result = new Array(props.length);
578
+ props.forEach((key, index) => {
579
+ result[index] = func(obj[key], key, obj);
580
+ });
581
+ return result;
582
+ }
583
+
584
+ /**
585
+ * Creates an object with the same keys as object and values generated by running each own enumerable string keyed property of object thru the function.
586
+ *
587
+ * The function is invoked with three arguments: (value, key, object).
588
+ *
589
+ * @param {object} obj
590
+ * @param {function} func
591
+ * @returns {object}
592
+ */
593
+ static mapObjectValues(obj, func) {
594
+ // Taken from lodash, see https://github.com/lodash/lodash/blob/master/mapValue.js
595
+ obj = Object(obj);
596
+ const result = {};
597
+ Object.keys(obj).forEach((key) => {
598
+ result[key] = func(obj[key], key, obj);
599
+ });
600
+ return result;
601
+ }
602
+
603
+ /**
604
+ * Creates a duplicate-free version of an array.
605
+ *
606
+ * If useEquals is set to true, uses the `Utils.equals` function for comparison instead of
607
+ * the JS === operator. Thus, if the array contains objects, you likely want to set
608
+ * `useEquals` to `true`.
609
+ *
610
+ * @param {array} array
611
+ * @param {boolean} useEquals
612
+ * @returns {array}
613
+ */
614
+ static unique(array, useEquals = false) {
615
+ if (useEquals) {
616
+ return array.filter((s1, pos, arr) => arr.findIndex(s2 => Utils.equals(s1, s2)) === pos);
617
+ }
618
+ else {
619
+ return [...new Set(array)];
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Computes the size of an array (number of array elements) or object (number of key-value-pairs).
625
+ *
626
+ * Returns 0 for all other data types.
627
+ *
628
+ * @param {*} obj
629
+ * @returns {integer}
630
+ */
631
+ static size(obj) {
632
+ if (typeof obj === 'object' && obj !== null) {
633
+ if (Array.isArray(obj)) {
634
+ return obj.length;
635
+ }
636
+ else {
637
+ return Object.keys(obj).length;
638
+ }
639
+ }
640
+ return 0;
641
+ }
642
+
643
+ /**
644
+ * Checks whether a variable is numeric.
645
+ *
646
+ * Numeric is every string with numeric data or a number, excluding NaN and finite numbers.
647
+ *
648
+ * @param {*} n - A variable to check.
649
+ * @returns {boolean} - `true` is the given variable is numeric, `false` otherwise.
650
+ */
651
+ static isNumeric(n) {
652
+ return !isNaN(parseFloat(n)) && isFinite(n);
653
+ }
654
+
655
+ /**
656
+ * Deep clone for JSON-compatible data.
657
+ *
658
+ * @param {*} x - The data to clone.
659
+ * @returns {*} - The cloned data.
660
+ */
661
+ static deepClone(x) {
662
+ return JSON.parse(JSON.stringify(x));
663
+ }
664
+
665
+ /**
666
+ * Normalize a URL (mostly handling leading and trailing slashes).
667
+ *
668
+ * @static
669
+ * @param {string} baseUrl - The URL to normalize
670
+ * @param {string} path - An optional path to add to the URL
671
+ * @returns {string} Normalized URL.
672
+ */
673
+ static normalizeUrl(baseUrl, path = null) {
674
+ let url = baseUrl.replace(/\/$/, ""); // Remove trailing slash from base URL
675
+ if (typeof path === 'string') {
676
+ if (path.substr(0, 1) !== '/') {
677
+ path = '/' + path; // Add leading slash to path
678
+ }
679
+ url = url + path.replace(/\/$/, ""); // Remove trailing slash from path
680
+ }
681
+ return url;
682
+ }
683
+
684
+ /**
685
+ * Replaces placeholders in this format: `{var}`.
686
+ *
687
+ * This can be used for the placeholders/variables in the openEO API's errors.json file.
688
+ *
689
+ * @param {string} message - The string to replace the placeholders in.
690
+ * @param {object} variables - A map with the placeholder names as keys and the replacement value as value.
691
+ */
692
+ static replacePlaceholders(message, variables = {}) {
693
+ if (typeof message === 'string' && Utils.isObject(variables)) {
694
+ for(var placeholder in variables) {
695
+ let vars = variables[placeholder];
696
+ message = message.replace('{' + placeholder + '}', Array.isArray(vars) ? vars.join("; ") : vars);
697
+ }
698
+ }
699
+ return message;
700
+ }
701
+
702
+ /**
703
+ * Compares two strings case-insensitive, including natural ordering for numbers.
704
+ *
705
+ * @param {string} a
706
+ * @param {string} b
707
+ * @returns {integer} Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
708
+ */
709
+ static compareStringCaseInsensitive(a, b) {
710
+ if (typeof a !== 'string') {
711
+ a = String(a);
712
+ }
713
+ if (typeof b !== 'string') {
714
+ b = String(b);
715
+ }
716
+ return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'});
717
+ }
718
+
719
+ /**
720
+ * Tries to make a string more readable by capitalizing it.
721
+ * Only applies to words with more than two characters.
722
+ *
723
+ * Supports converting from:
724
+ * - Snake Case (abc_def => Abc Def)
725
+ * - Kebab Case (abc-def => Abc Def)
726
+ * - Camel Case (abcDef => Abc Def)
727
+ *
728
+ * Doesn't capitalize if the words are not in any of the casing formats above.
729
+ *
730
+ * @param {*} strings - String(s) to make readable
731
+ * @param {string} arraySep - String to separate array elements with
732
+ * @returns {string}
733
+ */
734
+ static prettifyString(strings, arraySep = '; ') {
735
+ if (!Array.isArray(strings)) {
736
+ strings = [String(strings)];
737
+ }
738
+ strings = strings.map(str => {
739
+ if (str.length >= 3) {
740
+ const replacer = (_,a,b) => a + ' ' + b.toUpperCase();
741
+ if (str.includes('_')) {
742
+ // Snake case converter
743
+ str = str.replace(/([a-zA-Z\d])_([a-zA-Z\d])/g, replacer);
744
+ }
745
+ else if (str.includes('-')) {
746
+ // Kebab case converter
747
+ str = str.replace(/([a-zA-Z\d])-([a-zA-Z\d])/g, replacer);
748
+ }
749
+ else {
750
+ // Camelcase converter
751
+ str = str.replace(/([a-z])([A-Z])/g, replacer);
752
+ }
753
+ // Uppercase the first letter in the first word, too.
754
+ return str.charAt(0).toUpperCase() + str.substr(1);
755
+ }
756
+ return str;
757
+ });
758
+ return strings.join(arraySep);
759
+ }
760
+
761
+ /**
762
+ * Makes link lists from the openEO API more user-friendly.
763
+ *
764
+ * Supports:
765
+ * - Set a reasonable title, if not available. Make title more readable.
766
+ * - Sorting by title (see `sort` parameter)
767
+ * - Removing given relation types (`rel` property, see `ignoreRel` parameter)
768
+ *
769
+ * @param {array} linkList - List of links
770
+ * @param {boolean} sort - Enable/Disable sorting by title. Enabled (true) by default.
771
+ * @param {array} ignoreRel - A list of rel types to remove. By default, removes the self links (rel type = `self`).
772
+ * @returns {array}
773
+ */
774
+ static friendlyLinks(linkList, sort = true, ignoreRel = ['self']) {
775
+ let links = [];
776
+ if (!Array.isArray(linkList)) {
777
+ return links;
778
+ }
779
+
780
+ for(let link of linkList) {
781
+ link = Object.assign({}, link); // Make sure to work on a copy
782
+ if (typeof link.rel === 'string' && ignoreRel.includes(link.rel.toLowerCase())) {
783
+ continue;
784
+ }
785
+ if (typeof link.title !== 'string' || link.title.length === 0) {
786
+ if (typeof link.rel === 'string' && link.rel.length > 1) {
787
+ link.title = Utils.prettifyString(link.rel);
788
+ }
789
+ else {
790
+ link.title = link.href.replace(/^https?:\/\/(www.)?/i, '').replace(/\/$/i, '');
791
+ }
792
+ }
793
+ links.push(link);
794
+ }
795
+ if (sort) {
796
+ links.sort((a, b) => Utils.compareStringCaseInsensitive(a.title, b.title));
797
+ }
798
+ return links;
799
+ }
800
+
801
+ }
802
+
803
803
  module.exports = Utils;
804
804
 
805
805
  /***/ }),
@@ -807,115 +807,115 @@ module.exports = Utils;
807
807
  /***/ 304:
808
808
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
809
809
 
810
- const VersionCompare = __webpack_require__(246);
811
-
812
- /** Version Number related methods */
813
- class Versions {
814
-
815
- /**
816
- * Compare [semver](https://semver.org/) version strings.
817
- *
818
- * @param {string} firstVersion First version to compare
819
- * @param {string} secondVersion Second version to compare
820
- * @param {string|null} operator Optional; Arithmetic operator to use (>, >=, =, <=, <, !=). Defaults to `null`.
821
- * @returns {boolean|integer} If operator is not `null`: true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise. If operator is `null`: Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
822
- * ```
823
- */
824
- static compare(v1, v2, operator = null) {
825
- if (operator !== null) {
826
- return VersionCompare.compare(v1, v2, operator);
827
- }
828
- else {
829
- return VersionCompare(v1, v2);
830
- }
831
- }
832
-
833
- /**
834
- * Validate [semver](https://semver.org/) version strings.
835
- *
836
- * @param {*} version - Version number to validate
837
- * @returns - `true` if the version number is a valid semver version number, `false` otherwise.
838
- */
839
- static validate(version) {
840
- return VersionCompare.validate(version);
841
- }
842
-
843
- /**
844
- * Tries to determine the most suitable version from a well-known discovery document that software is compatible to.
845
- *
846
- * @static
847
- * @param {array} wkVersions - A well-known discovery document compliant to the API specification.
848
- * @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
849
- * @param {string|null} minVersion - The minimum version that should be returned.
850
- * @param {string|null} maxVersion - The maximum version that should be returned.
851
- * @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable.
852
- */
853
- static findCompatible(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
854
- if (!Array.isArray(wkVersions) || wkVersions.length === 0) {
855
- return [];
856
- }
857
-
858
- let compatible = wkVersions.filter(c => {
859
- if (typeof c.url === 'string' && Versions.validate(c.api_version)) {
860
- let hasMinVer = Versions.validate(minVersion);
861
- let hasMaxVer = Versions.validate(maxVersion);
862
- if (hasMinVer && hasMaxVer) {
863
- return Versions.compare(c.api_version, minVersion, ">=") && Versions.compare(c.api_version, maxVersion, "<=");
864
- }
865
- else if (hasMinVer) {
866
- return Versions.compare(c.api_version, minVersion, ">=");
867
- }
868
- else if (hasMaxVer) {
869
- return Versions.compare(c.api_version, maxVersion, "<=");
870
- }
871
- else {
872
- return true;
873
- }
874
- }
875
- return false;
876
- });
877
- if (compatible.length === 0) {
878
- return [];
879
- }
880
-
881
- return compatible.sort((c1, c2) => {
882
- let p1 = c1.production === true;
883
- let p2 = c2.production === true;
884
- if (!preferProduction || p1 === p2) {
885
- return Versions.compare(c1.api_version, c2.api_version) * -1; // `* -1` to sort in descending order.
886
- }
887
- else if (p1) {
888
- return -1;
889
- }
890
- else {
891
- return 1;
892
- }
893
- });
894
- }
895
-
896
- /**
897
- * Find the latest version from well-known discovery that applies to the specified rules.
898
- *
899
- * This is basically the same as calling `findCompatible` and using the first element from the result.
900
- *
901
- * @param {array} wkVersions - A well-known discovery document compliant to the API specification.
902
- * @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
903
- * @param {string|null} minVersion - The minimum version that should be returned.
904
- * @param {string|null} maxVersion - The maximum version that should be returned.
905
- * @returns {object|null}
906
- */
907
- static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
908
- let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion);
909
- if (versions.length > 0) {
910
- return versions[0];
911
- }
912
- else {
913
- return null;
914
- }
915
- }
916
-
917
- }
918
-
810
+ const { compare, compareVersions, validate } = __webpack_require__(385);
811
+
812
+ /** Version Number related methods */
813
+ class Versions {
814
+
815
+ /**
816
+ * Compare [semver](https://semver.org/) version strings.
817
+ *
818
+ * @param {string} firstVersion First version to compare
819
+ * @param {string} secondVersion Second version to compare
820
+ * @param {string|null} operator Optional; Arithmetic operator to use (>, >=, =, <=, <, !=). Defaults to `null`.
821
+ * @returns {boolean|integer} If operator is not `null`: true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise. If operator is `null`: Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
822
+ * ```
823
+ */
824
+ static compare(v1, v2, operator = null) {
825
+ if (operator !== null) {
826
+ return compare(v1, v2, operator);
827
+ }
828
+ else {
829
+ return compareVersions(v1, v2);
830
+ }
831
+ }
832
+
833
+ /**
834
+ * Validate [semver](https://semver.org/) version strings.
835
+ *
836
+ * @param {*} version - Version number to validate
837
+ * @returns - `true` if the version number is a valid semver version number, `false` otherwise.
838
+ */
839
+ static validate(version) {
840
+ return validate(version);
841
+ }
842
+
843
+ /**
844
+ * Tries to determine the most suitable version from a well-known discovery document that software is compatible to.
845
+ *
846
+ * @static
847
+ * @param {array} wkVersions - A well-known discovery document compliant to the API specification.
848
+ * @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
849
+ * @param {string|null} minVersion - The minimum version that should be returned.
850
+ * @param {string|null} maxVersion - The maximum version that should be returned.
851
+ * @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable.
852
+ */
853
+ static findCompatible(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
854
+ if (!Array.isArray(wkVersions) || wkVersions.length === 0) {
855
+ return [];
856
+ }
857
+
858
+ let compatible = wkVersions.filter(c => {
859
+ if (typeof c.url === 'string' && Versions.validate(c.api_version)) {
860
+ let hasMinVer = Versions.validate(minVersion);
861
+ let hasMaxVer = Versions.validate(maxVersion);
862
+ if (hasMinVer && hasMaxVer) {
863
+ return Versions.compare(c.api_version, minVersion, ">=") && Versions.compare(c.api_version, maxVersion, "<=");
864
+ }
865
+ else if (hasMinVer) {
866
+ return Versions.compare(c.api_version, minVersion, ">=");
867
+ }
868
+ else if (hasMaxVer) {
869
+ return Versions.compare(c.api_version, maxVersion, "<=");
870
+ }
871
+ else {
872
+ return true;
873
+ }
874
+ }
875
+ return false;
876
+ });
877
+ if (compatible.length === 0) {
878
+ return [];
879
+ }
880
+
881
+ return compatible.sort((c1, c2) => {
882
+ let p1 = c1.production === true;
883
+ let p2 = c2.production === true;
884
+ if (!preferProduction || p1 === p2) {
885
+ return Versions.compare(c1.api_version, c2.api_version) * -1; // `* -1` to sort in descending order.
886
+ }
887
+ else if (p1) {
888
+ return -1;
889
+ }
890
+ else {
891
+ return 1;
892
+ }
893
+ });
894
+ }
895
+
896
+ /**
897
+ * Find the latest version from well-known discovery that applies to the specified rules.
898
+ *
899
+ * This is basically the same as calling `findCompatible` and using the first element from the result.
900
+ *
901
+ * @param {array} wkVersions - A well-known discovery document compliant to the API specification.
902
+ * @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
903
+ * @param {string|null} minVersion - The minimum version that should be returned.
904
+ * @param {string|null} maxVersion - The maximum version that should be returned.
905
+ * @returns {object|null}
906
+ */
907
+ static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
908
+ let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion);
909
+ if (versions.length > 0) {
910
+ return versions[0];
911
+ }
912
+ else {
913
+ return null;
914
+ }
915
+ }
916
+
917
+ }
918
+
919
919
  module.exports = Versions;
920
920
 
921
921
  /***/ }),
@@ -927,7 +927,7 @@ module.exports = Versions;
927
927
  // see https://github.com/stac-utils/pystac/tree/v0.5.4/pystac/serialization/migrate.py
928
928
  // and https://github.com/Open-EO/openeo-js-commons/tree/v1.2.0/src/migrate/collections.js
929
929
 
930
- var compareVersions = __webpack_require__(246);
930
+ var compareVersions = __webpack_require__(139);
931
931
 
932
932
  const LATEST_VERSION = '1.0.0';
933
933
  const DONE = true; // This is used to verify in code coverage whether something has been used or not
@@ -1899,34 +1899,155 @@ module.exports = Migrate;
1899
1899
 
1900
1900
  /***/ }),
1901
1901
 
1902
- /***/ 147:
1903
- /***/ ((module) => {
1902
+ /***/ 139:
1903
+ /***/ (function(module, exports) {
1904
1904
 
1905
- /**
1906
- * The base class for authentication providers such as Basic and OpenID Connect.
1907
- *
1908
- * @abstract
1909
- */
1910
- class AuthProvider {
1911
- /**
1912
- * Creates a new OidcProvider instance to authenticate using OpenID Connect.
1913
- *
1914
- * @param {string} type - The type of the authentication procedure as specified by the API, e.g. `oidc` or `basic`.
1915
- * @param {Connection} connection - A Connection object representing an established connection to an openEO back-end.
1916
- * @param {AuthProviderMeta} options - Options
1917
- */
1918
- constructor(type, connection, options) {
1919
- this.id = options.id || null;
1920
- this.title = options.title || "";
1921
- this.description = options.description || "";
1922
- this.type = type;
1923
- /**
1924
- * @protected
1925
- * @type {Connection}
1926
- */
1927
- this.connection = connection;
1928
- this.token = null;
1929
- }
1905
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* global define */
1906
+ (function (root, factory) {
1907
+ /* istanbul ignore next */
1908
+ if (true) {
1909
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
1910
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
1911
+ (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
1912
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
1913
+ } else {}
1914
+ }(this, function () {
1915
+
1916
+ var semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
1917
+
1918
+ function indexOrEnd(str, q) {
1919
+ return str.indexOf(q) === -1 ? str.length : str.indexOf(q);
1920
+ }
1921
+
1922
+ function split(v) {
1923
+ var c = v.replace(/^v/, '').replace(/\+.*$/, '');
1924
+ var patchIndex = indexOrEnd(c, '-');
1925
+ var arr = c.substring(0, patchIndex).split('.');
1926
+ arr.push(c.substring(patchIndex + 1));
1927
+ return arr;
1928
+ }
1929
+
1930
+ function tryParse(v) {
1931
+ return isNaN(Number(v)) ? v : Number(v);
1932
+ }
1933
+
1934
+ function validate(version) {
1935
+ if (typeof version !== 'string') {
1936
+ throw new TypeError('Invalid argument expected string');
1937
+ }
1938
+ if (!semver.test(version)) {
1939
+ throw new Error('Invalid argument not valid semver (\''+version+'\' received)');
1940
+ }
1941
+ }
1942
+
1943
+ function compareVersions(v1, v2) {
1944
+ [v1, v2].forEach(validate);
1945
+
1946
+ var s1 = split(v1);
1947
+ var s2 = split(v2);
1948
+
1949
+ for (var i = 0; i < Math.max(s1.length - 1, s2.length - 1); i++) {
1950
+ var n1 = parseInt(s1[i] || 0, 10);
1951
+ var n2 = parseInt(s2[i] || 0, 10);
1952
+
1953
+ if (n1 > n2) return 1;
1954
+ if (n2 > n1) return -1;
1955
+ }
1956
+
1957
+ var sp1 = s1[s1.length - 1];
1958
+ var sp2 = s2[s2.length - 1];
1959
+
1960
+ if (sp1 && sp2) {
1961
+ var p1 = sp1.split('.').map(tryParse);
1962
+ var p2 = sp2.split('.').map(tryParse);
1963
+
1964
+ for (i = 0; i < Math.max(p1.length, p2.length); i++) {
1965
+ if (p1[i] === undefined || typeof p2[i] === 'string' && typeof p1[i] === 'number') return -1;
1966
+ if (p2[i] === undefined || typeof p1[i] === 'string' && typeof p2[i] === 'number') return 1;
1967
+
1968
+ if (p1[i] > p2[i]) return 1;
1969
+ if (p2[i] > p1[i]) return -1;
1970
+ }
1971
+ } else if (sp1 || sp2) {
1972
+ return sp1 ? -1 : 1;
1973
+ }
1974
+
1975
+ return 0;
1976
+ };
1977
+
1978
+ var allowedOperators = [
1979
+ '>',
1980
+ '>=',
1981
+ '=',
1982
+ '<',
1983
+ '<='
1984
+ ];
1985
+
1986
+ var operatorResMap = {
1987
+ '>': [1],
1988
+ '>=': [0, 1],
1989
+ '=': [0],
1990
+ '<=': [-1, 0],
1991
+ '<': [-1]
1992
+ };
1993
+
1994
+ function validateOperator(op) {
1995
+ if (typeof op !== 'string') {
1996
+ throw new TypeError('Invalid operator type, expected string but got ' + typeof op);
1997
+ }
1998
+ if (allowedOperators.indexOf(op) === -1) {
1999
+ throw new TypeError('Invalid operator, expected one of ' + allowedOperators.join('|'));
2000
+ }
2001
+ }
2002
+
2003
+ compareVersions.validate = function(version) {
2004
+ return typeof version === 'string' && semver.test(version);
2005
+ }
2006
+
2007
+ compareVersions.compare = function (v1, v2, operator) {
2008
+ // Validate operator
2009
+ validateOperator(operator);
2010
+
2011
+ // since result of compareVersions can only be -1 or 0 or 1
2012
+ // a simple map can be used to replace switch
2013
+ var res = compareVersions(v1, v2);
2014
+ return operatorResMap[operator].indexOf(res) > -1;
2015
+ }
2016
+
2017
+ return compareVersions;
2018
+ }));
2019
+
2020
+
2021
+ /***/ }),
2022
+
2023
+ /***/ 147:
2024
+ /***/ ((module) => {
2025
+
2026
+ /**
2027
+ * The base class for authentication providers such as Basic and OpenID Connect.
2028
+ *
2029
+ * @abstract
2030
+ */
2031
+ class AuthProvider {
2032
+ /**
2033
+ * Creates a new OidcProvider instance to authenticate using OpenID Connect.
2034
+ *
2035
+ * @param {string} type - The type of the authentication procedure as specified by the API, e.g. `oidc` or `basic`.
2036
+ * @param {Connection} connection - A Connection object representing an established connection to an openEO back-end.
2037
+ * @param {AuthProviderMeta} options - Options
2038
+ */
2039
+ constructor(type, connection, options) {
2040
+ this.id = options.id || null;
2041
+ this.title = options.title || "";
2042
+ this.description = options.description || "";
2043
+ this.type = type;
2044
+ /**
2045
+ * @protected
2046
+ * @type {Connection}
2047
+ */
2048
+ this.connection = connection;
2049
+ this.token = null;
2050
+ }
1930
2051
 
1931
2052
  /**
1932
2053
  * Get an identifier for the auth provider (combination of the type + provider identifier).
@@ -4101,6 +4222,52 @@ class Capabilities {
4101
4222
  return Array.isArray(this.data.links) ? this.data.links : [];
4102
4223
  }
4103
4224
 
4225
+ /**
4226
+ * Returns list of backends in the federation.
4227
+ *
4228
+ * @returns {Array.<FederationBackend>} Array of backends
4229
+ */
4230
+ listFederation() {
4231
+ let federation = [];
4232
+ if (Utils.isObject(this.data.federation)) {
4233
+ // convert to array and add keys as `id` property
4234
+ for (const [key, backend] of Object.entries(this.data.federation)) {
4235
+ // fresh object to avoid `id` showing up in this.data.federation
4236
+ federation.push({
4237
+ id: key,
4238
+ ...backend
4239
+ });
4240
+ }
4241
+ }
4242
+ return federation;
4243
+ }
4244
+
4245
+ /**
4246
+ * Given just the string ID of a backend within the federation, returns that backend's full details as a FederationBackend object.
4247
+ *
4248
+ * @param {string} backendId - The ID of a backend within the federation
4249
+ * @returns {FederationBackend} The full details of the backend
4250
+ */
4251
+ getFederationBackend(backendId) {
4252
+ // Add `id` property to make it a proper FederationBackend object
4253
+ // If backendId doesn't exist in this.data.federation, will contain just the `id` field (intended behaviour)
4254
+ return {
4255
+ id: backendId,
4256
+ ...this.data.federation[backendId]
4257
+ };
4258
+ }
4259
+
4260
+ /**
4261
+ * Given a list of string IDs of backends within the federation, returns those backends' full details as FederationBackend objects.
4262
+ *
4263
+ * @param {Array<string>} backendIds - The IDs of backends within the federation
4264
+ * @returns {Array<FederationBackend>} An array in the same order as the input, containing for each position the full details of the backend
4265
+ */
4266
+ getFederationBackends(backendIds) {
4267
+ // Let 'single case' function do the work, but pass `this` so that `this.data.federation` can be accessed in the callback context
4268
+ return backendIds.map(this.getFederationBackend, this);
4269
+ }
4270
+
4104
4271
  /**
4105
4272
  * Lists all supported features.
4106
4273
  *
@@ -4193,6 +4360,14 @@ const UserProcess = __webpack_require__(806);
4193
4360
  const Service = __webpack_require__(497);
4194
4361
  const Builder = __webpack_require__(425);
4195
4362
  const BuilderNode = __webpack_require__(804);
4363
+ const {
4364
+ CollectionPages,
4365
+ ItemPages,
4366
+ JobPages,
4367
+ ProcessPages,
4368
+ ServicePages,
4369
+ UserFilePages
4370
+ } = __webpack_require__(226);
4196
4371
  const CONFORMANCE_RELS = ['conformance', 'http://www.opengis.net/def/rel/ogc/1.0/conformance'];
4197
4372
 
4198
4373
  /**
@@ -4277,13 +4452,13 @@ class Connection {
4277
4452
  * @throws {Error}
4278
4453
  */
4279
4454
  async init() {
4280
- let response = await this._get('/');
4281
- let data = Object.assign({}, response.data);
4455
+ const response = await this._get('/');
4456
+ const data = Object.assign({}, response.data);
4282
4457
  data.links = this.makeLinksAbsolute(data.links, response);
4283
4458
  if (!Array.isArray(data.conformsTo) && Array.isArray(data.links)) {
4284
- let conformanceLink = this._getLinkHref(data.links, CONFORMANCE_RELS);
4459
+ const conformanceLink = this._getLinkHref(data.links, CONFORMANCE_RELS);
4285
4460
  if (conformanceLink) {
4286
- let response2 = await this._get(conformanceLink);
4461
+ const response2 = await this._get(conformanceLink);
4287
4462
  if (Utils.isObject(response2.data) && Array.isArray(response2.data.conformsTo)) {
4288
4463
  data.conformsTo = response2.data.conformsTo;
4289
4464
  }
@@ -4304,10 +4479,10 @@ class Connection {
4304
4479
  if (this.processes.count() === 0) {
4305
4480
  return;
4306
4481
  }
4307
- let promises = this.processes.namespaces().map(namespace => {
4482
+ const promises = this.processes.namespaces().map(namespace => {
4308
4483
  let fn = () => Promise.resolve();
4309
4484
  if (namespace === 'user') {
4310
- let userProcesses = this.processes.namespace('user');
4485
+ const userProcesses = this.processes.namespace('user');
4311
4486
  if (!this.isAuthenticated()) {
4312
4487
  fn = () => this.processes.remove(null, 'user') ? Promise.resolve() : Promise.reject(new Error("Can't clear user processes"));
4313
4488
  } else if (this.capabilities().hasFeature('listUserProcesses')) {
@@ -4356,7 +4531,7 @@ class Connection {
4356
4531
  * @throws {Error}
4357
4532
  */
4358
4533
  async listFileTypes() {
4359
- let response = await this._get('/file_formats');
4534
+ const response = await this._get('/file_formats');
4360
4535
  return new FileTypes(response.data);
4361
4536
  }
4362
4537
 
@@ -4368,7 +4543,7 @@ class Connection {
4368
4543
  * @throws {Error}
4369
4544
  */
4370
4545
  async listServiceTypes() {
4371
- let response = await this._get('/service_types');
4546
+ const response = await this._get('/service_types');
4372
4547
  return response.data;
4373
4548
  }
4374
4549
 
@@ -4380,7 +4555,7 @@ class Connection {
4380
4555
  * @throws {Error}
4381
4556
  */
4382
4557
  async listUdfRuntimes() {
4383
- let response = await this._get('/udf_runtimes');
4558
+ const response = await this._get('/udf_runtimes');
4384
4559
  return response.data;
4385
4560
  }
4386
4561
 
@@ -4388,22 +4563,27 @@ class Connection {
4388
4563
  * List all collections available on the back-end.
4389
4564
  *
4390
4565
  * The collections returned always comply to the latest STAC version (currently 1.0.0).
4566
+ * This function adds a self link to the response if not present.
4391
4567
  *
4392
4568
  * @async
4393
4569
  * @returns {Promise<Collections>} A response compatible to the API specification.
4394
4570
  * @throws {Error}
4395
4571
  */
4396
4572
  async listCollections() {
4397
- let response = await this._get('/collections');
4398
- if (Utils.isObject(response.data) && Array.isArray(response.data.collections)) {
4399
- response.data.collections = response.data.collections.map(collection => {
4400
- if (collection.stac_version) {
4401
- return StacMigrate.collection(collection);
4402
- }
4403
- return collection;
4404
- });
4405
- }
4406
- return response.data;
4573
+ const pages = this.paginateCollections(null);
4574
+ return await pages.nextPage([], false);
4575
+ }
4576
+
4577
+ /**
4578
+ * Paginate through the collections available on the back-end.
4579
+ *
4580
+ * The collections returned always comply to the latest STAC version (currently 1.0.0).
4581
+ *
4582
+ * @param {?number} [limit=50] - The number of collections per request/page as integer. If `null`, requests all collections.
4583
+ * @returns {CollectionPages} A paged list of collections.
4584
+ */
4585
+ paginateCollections(limit = 50) {
4586
+ return new CollectionPages(this, limit);
4407
4587
  }
4408
4588
 
4409
4589
  /**
@@ -4417,7 +4597,7 @@ class Connection {
4417
4597
  * @throws {Error}
4418
4598
  */
4419
4599
  async describeCollection(collectionId) {
4420
- let response = await this._get('/collections/' + collectionId);
4600
+ const response = await this._get('/collections/' + collectionId);
4421
4601
  if (response.data.stac_version) {
4422
4602
  return StacMigrate.collection(response.data);
4423
4603
  } else {
@@ -4426,13 +4606,12 @@ class Connection {
4426
4606
  }
4427
4607
 
4428
4608
  /**
4429
- * Loads items for a specific image collection.
4609
+ * Paginate through items for a specific collection.
4610
+ *
4430
4611
  * May not be available for all collections.
4431
4612
  *
4432
4613
  * The items returned always comply to the latest STAC version (currently 1.0.0).
4433
4614
  *
4434
- * This is an experimental API and is subject to change.
4435
- *
4436
4615
  * @async
4437
4616
  * @param {string} collectionId - Collection ID to request items for.
4438
4617
  * @param {?Array.<number>} [spatialExtent=null] - Limits the items to the given bounding box in WGS84:
@@ -4445,46 +4624,28 @@ class Connection {
4445
4624
  * each must be either an RFC 3339 compatible string or a Date object.
4446
4625
  * Also supports open intervals by setting one of the boundaries to `null`, but never both.
4447
4626
  * @param {?number} [limit=null] - The amount of items per request/page as integer. If `null` (default), the back-end decides.
4448
- * @yields {Promise<ItemCollection>} A response compatible to the API specification.
4627
+ * @returns {Promise<ItemPages>} A response compatible to the API specification.
4449
4628
  * @throws {Error}
4450
4629
  */
4451
- async *listCollectionItems(collectionId, spatialExtent = null, temporalExtent = null, limit = null) {
4452
- let page = 1;
4453
- let nextUrl = '/collections/' + collectionId + '/items';
4454
- while (nextUrl) {
4455
- let params = {};
4456
- if (page === 1) {
4457
- if (Array.isArray(spatialExtent)) {
4458
- params.bbox = spatialExtent.join(',');
4459
- }
4460
- if (Array.isArray(temporalExtent)) {
4461
- params.datetime = temporalExtent.map(e => {
4462
- if (e instanceof Date) {
4463
- return e.toISOString();
4464
- } else if (typeof e === 'string') {
4465
- return e;
4466
- }
4467
- return '..'; // Open date range
4468
- }).join('/');
4630
+ listCollectionItems(collectionId, spatialExtent = null, temporalExtent = null, limit = null) {
4631
+ let params = {};
4632
+ if (Array.isArray(spatialExtent)) {
4633
+ params.bbox = spatialExtent.join(',');
4634
+ }
4635
+ if (Array.isArray(temporalExtent)) {
4636
+ params.datetime = temporalExtent.map(e => {
4637
+ if (e instanceof Date) {
4638
+ return e.toISOString();
4639
+ } else if (typeof e === 'string') {
4640
+ return e;
4469
4641
  }
4470
- if (limit > 0) {
4471
- params.limit = limit;
4472
- }
4473
- }
4474
- let response = await this._get(nextUrl, params);
4475
- if (Utils.isObject(response.data) && Array.isArray(response.data.features)) {
4476
- response.data.features = response.data.features.map(item => {
4477
- if (item.stac_version) {
4478
- return StacMigrate.item(item);
4479
- }
4480
- return item;
4481
- });
4482
- }
4483
- yield response.data;
4484
- page++;
4485
- let links = this.makeLinksAbsolute(response.data.links);
4486
- nextUrl = this._getLinkHref(links, 'next');
4642
+ return '..'; // Open date range
4643
+ }).join('/');
4644
+ }
4645
+ if (limit > 0) {
4646
+ params.limit = limit;
4487
4647
  }
4648
+ return new ItemPages(this, collectionId, params, limit);
4488
4649
  }
4489
4650
 
4490
4651
  /**
@@ -4507,7 +4668,7 @@ class Connection {
4507
4668
  }
4508
4669
 
4509
4670
  /**
4510
- * List processes available on the back-end.
4671
+ * List all processes available on the back-end.
4511
4672
  *
4512
4673
  * Requests pre-defined processes by default.
4513
4674
  * Set the namespace parameter to request processes from a specific namespace.
@@ -4515,27 +4676,33 @@ class Connection {
4515
4676
  * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given.
4516
4677
  * The namespaces are then listed in the property `namespaces`.
4517
4678
  *
4679
+ * This function adds a self link to the response if not present.
4680
+ *
4518
4681
  * @async
4519
4682
  * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
4520
4683
  * @returns {Promise<Processes>} - A response compatible to the API specification.
4521
4684
  * @throws {Error}
4522
4685
  */
4523
4686
  async listProcesses(namespace = null) {
4524
- if (!namespace) {
4525
- namespace = 'backend';
4526
- }
4527
- let path = namespace === 'backend' ? '/processes' : `/processes/${this.normalizeNamespace(namespace)}`;
4528
- let response = await this._get(path);
4529
- if (!Utils.isObject(response.data) || !Array.isArray(response.data.processes)) {
4530
- throw new Error('Invalid response received for processes');
4531
- }
4687
+ const pages = this.paginateProcesses(namespace);
4688
+ return await pages.nextPage([], false);
4689
+ }
4532
4690
 
4533
- // Store processes in cache
4534
- this.processes.remove(null, namespace);
4535
- this.processes.addAll(response.data.processes, namespace);
4536
- return Object.assign(response.data, {
4537
- processes: this.processes.namespace(namespace)
4538
- });
4691
+ /**
4692
+ * Paginate through the processes available on the back-end.
4693
+ *
4694
+ * Requests pre-defined processes by default.
4695
+ * Set the namespace parameter to request processes from a specific namespace.
4696
+ *
4697
+ * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given.
4698
+ * The namespaces are then listed in the property `namespaces`.
4699
+ *
4700
+ * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
4701
+ * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes.
4702
+ * @returns {ProcessPages} A paged list of processes.
4703
+ */
4704
+ paginateProcesses(namespace = null, limit = 50) {
4705
+ return new ProcessPages(this, limit, namespace);
4539
4706
  }
4540
4707
 
4541
4708
  /**
@@ -4555,7 +4722,7 @@ class Connection {
4555
4722
  if (namespace === 'backend') {
4556
4723
  await this.listProcesses();
4557
4724
  } else {
4558
- let response = await this._get(`/processes/${this.normalizeNamespace(namespace)}/${processId}`);
4725
+ const response = await this._get(`/processes/${this.normalizeNamespace(namespace)}/${processId}`);
4559
4726
  if (!Utils.isObject(response.data) || typeof response.data.id !== 'string') {
4560
4727
  throw new Error('Invalid response received for process');
4561
4728
  }
@@ -4591,15 +4758,15 @@ class Connection {
4591
4758
  return this.authProviderList;
4592
4759
  }
4593
4760
  this.authProviderList = [];
4594
- let cap = this.capabilities();
4761
+ const cap = this.capabilities();
4595
4762
 
4596
4763
  // Add OIDC providers
4597
4764
  if (cap.hasFeature('authenticateOIDC')) {
4598
- let res = await this._get('/credentials/oidc');
4599
- let oidcFactory = this.getOidcProviderFactory();
4765
+ const res = await this._get('/credentials/oidc');
4766
+ const oidcFactory = this.getOidcProviderFactory();
4600
4767
  if (Utils.isObject(res.data) && Array.isArray(res.data.providers) && typeof oidcFactory === 'function') {
4601
4768
  for (let i in res.data.providers) {
4602
- let obj = oidcFactory(res.data.providers[i]);
4769
+ const obj = oidcFactory(res.data.providers[i]);
4603
4770
  if (obj instanceof AuthProvider) {
4604
4771
  this.authProviderList.push(obj);
4605
4772
  }
@@ -4677,7 +4844,7 @@ class Connection {
4677
4844
  * @see Connection#listAuthProviders
4678
4845
  */
4679
4846
  async authenticateBasic(username, password) {
4680
- let basic = new BasicProvider(this);
4847
+ const basic = new BasicProvider(this);
4681
4848
  await basic.login(username, password);
4682
4849
  }
4683
4850
 
@@ -4770,7 +4937,7 @@ class Connection {
4770
4937
  * @returns {AuthProvider}
4771
4938
  */
4772
4939
  setAuthToken(type, providerId, token) {
4773
- let provider = new AuthProvider(type, this, {
4940
+ const provider = new AuthProvider(type, this, {
4774
4941
  id: providerId,
4775
4942
  title: "Custom",
4776
4943
  description: ""
@@ -4790,21 +4957,30 @@ class Connection {
4790
4957
  * @throws {Error}
4791
4958
  */
4792
4959
  async describeAccount() {
4793
- let response = await this._get('/me');
4960
+ const response = await this._get('/me');
4794
4961
  return response.data;
4795
4962
  }
4796
4963
 
4797
4964
  /**
4798
- * Lists all files from the user workspace.
4965
+ * List all files from the user workspace.
4799
4966
  *
4800
4967
  * @async
4801
4968
  * @returns {Promise<ResponseArray.<UserFile>>} A list of files.
4802
4969
  * @throws {Error}
4803
4970
  */
4804
4971
  async listFiles() {
4805
- let response = await this._get('/files');
4806
- let files = response.data.files.map(f => new UserFile(this, f.path).setAll(f));
4807
- return this._toResponseArray(files, response.data);
4972
+ const pages = this.paginateFiles(null);
4973
+ return await pages.nextPage();
4974
+ }
4975
+
4976
+ /**
4977
+ * Paginate through the files from the user workspace.
4978
+ *
4979
+ * @param {?number} [limit=50] - The number of files per request/page as integer. If `null`, requests all files.
4980
+ * @returns {ServicePages} A paged list of files.
4981
+ */
4982
+ paginateFiles(limit = 50) {
4983
+ return new UserFilePages(this, limit);
4808
4984
  }
4809
4985
 
4810
4986
  /**
@@ -4835,7 +5011,7 @@ class Connection {
4835
5011
  if (targetPath === null) {
4836
5012
  targetPath = Environment.fileNameForUpload(source);
4837
5013
  }
4838
- let file = await this.getFile(targetPath);
5014
+ const file = await this.getFile(targetPath);
4839
5015
  return await file.uploadFile(source, statusCallback, abortController);
4840
5016
  }
4841
5017
 
@@ -4881,20 +5057,22 @@ class Connection {
4881
5057
  *
4882
5058
  * @async
4883
5059
  * @param {Process} process - User-defined process to validate.
4884
- * @returns {Promise<Array.<ApiError>>} errors - A list of API compatible error objects. A valid process returns an empty list.
5060
+ * @returns {Promise<ValidationResult>} errors - A list of API compatible error objects. A valid process returns an empty list.
4885
5061
  * @throws {Error}
4886
5062
  */
4887
5063
  async validateProcess(process) {
4888
- let response = await this._post('/validation', this._normalizeUserProcess(process).process);
5064
+ const response = await this._post('/validation', this._normalizeUserProcess(process).process);
4889
5065
  if (Array.isArray(response.data.errors)) {
4890
- return response.data.errors;
5066
+ const errors = response.data.errors;
5067
+ errors['federation:backends'] = Array.isArray(response.data['federation:missing']) ? response.data['federation:missing'] : [];
5068
+ return errors;
4891
5069
  } else {
4892
5070
  throw new Error("Invalid validation response received.");
4893
5071
  }
4894
5072
  }
4895
5073
 
4896
5074
  /**
4897
- * Lists all user-defined processes of the authenticated user.
5075
+ * List all user-defined processes of the authenticated user.
4898
5076
  *
4899
5077
  * @async
4900
5078
  * @param {Array.<UserProcess>} [oldProcesses=[]] - A list of existing user-defined processes to update.
@@ -4902,27 +5080,18 @@ class Connection {
4902
5080
  * @throws {Error}
4903
5081
  */
4904
5082
  async listUserProcesses(oldProcesses = []) {
4905
- let response = await this._get('/process_graphs');
4906
- if (!Utils.isObject(response.data) || !Array.isArray(response.data.processes)) {
4907
- throw new Error('Invalid response received for processes');
4908
- }
4909
-
4910
- // Remove existing processes from cache
4911
- this.processes.remove(null, 'user');
4912
-
4913
- // Update existing processes if needed
4914
- let newProcesses = response.data.processes.map(newProcess => {
4915
- let process = oldProcesses.find(oldProcess => oldProcess.id === newProcess.id);
4916
- if (!process) {
4917
- process = new UserProcess(this, newProcess.id);
4918
- }
4919
- return process.setAll(newProcess);
4920
- });
5083
+ const pages = this.paginateUserProcesses(null);
5084
+ return await pages.nextPage(oldProcesses);
5085
+ }
4921
5086
 
4922
- // Store plain JS variant (i.e. no Job objects involved) of processes in cache
4923
- let jsonProcesses = oldProcesses.length > 0 ? newProcesses.map(p => p.toJSON()) : response.data.processes;
4924
- this.processes.addAll(jsonProcesses, 'user');
4925
- return this._toResponseArray(newProcesses, response.data);
5087
+ /**
5088
+ * Paginates through the user-defined processes of the authenticated user.
5089
+ *
5090
+ * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes.
5091
+ * @returns {ProcessPages} A paged list of user-defined processes.
5092
+ */
5093
+ paginateUserProcesses(limit = 50) {
5094
+ return this.paginateProcesses('user', limit);
4926
5095
  }
4927
5096
 
4928
5097
  /**
@@ -4935,7 +5104,7 @@ class Connection {
4935
5104
  * @throws {Error}
4936
5105
  */
4937
5106
  async setUserProcess(id, process) {
4938
- let pg = new UserProcess(this, id);
5107
+ const pg = new UserProcess(this, id);
4939
5108
  return await pg.replaceUserProcess(process);
4940
5109
  }
4941
5110
 
@@ -4948,7 +5117,7 @@ class Connection {
4948
5117
  * @throws {Error}
4949
5118
  */
4950
5119
  async getUserProcess(id) {
4951
- let pg = new UserProcess(this, id);
5120
+ const pg = new UserProcess(this, id);
4952
5121
  return await pg.describeUserProcess();
4953
5122
  }
4954
5123
 
@@ -4966,12 +5135,12 @@ class Connection {
4966
5135
  * @returns {Promise<SyncResult>} - An object with the data and some metadata.
4967
5136
  */
4968
5137
  async computeResult(process, plan = null, budget = null, abortController = null, additional = {}) {
4969
- let requestBody = this._normalizeUserProcess(process, Object.assign({}, additional, {
5138
+ const requestBody = this._normalizeUserProcess(process, Object.assign({}, additional, {
4970
5139
  plan: plan,
4971
5140
  budget: budget
4972
5141
  }));
4973
- let response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
4974
- let syncResult = {
5142
+ const response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
5143
+ const syncResult = {
4975
5144
  data: response.data,
4976
5145
  costs: null,
4977
5146
  type: null,
@@ -4983,15 +5152,15 @@ class Connection {
4983
5152
  if (typeof response.headers['content-type'] === 'string') {
4984
5153
  syncResult.type = response.headers['content-type'];
4985
5154
  }
4986
- let links = Array.isArray(response.headers.link) ? response.headers.link : [response.headers.link];
5155
+ const links = Array.isArray(response.headers.link) ? response.headers.link : [response.headers.link];
4987
5156
  for (let link of links) {
4988
5157
  if (typeof link !== 'string') {
4989
5158
  continue;
4990
5159
  }
4991
- let logs = link.match(/^<([^>]+)>;\s?rel="monitor"/i);
5160
+ const logs = link.match(/^<([^>]+)>;\s?rel="monitor"/i);
4992
5161
  if (Array.isArray(logs) && logs.length > 1) {
4993
5162
  try {
4994
- let logsResponse = await this._get(logs[1]);
5163
+ const logsResponse = await this._get(logs[1]);
4995
5164
  if (Utils.isObject(logsResponse.data) && Array.isArray(logsResponse.data.logs)) {
4996
5165
  syncResult.logs = logsResponse.data.logs;
4997
5166
  }
@@ -5021,13 +5190,13 @@ class Connection {
5021
5190
  * @throws {Error}
5022
5191
  */
5023
5192
  async downloadResult(process, targetPath, plan = null, budget = null, abortController = null) {
5024
- let response = await this.computeResult(process, plan, budget, abortController);
5193
+ const response = await this.computeResult(process, plan, budget, abortController);
5025
5194
  // @ts-ignore
5026
5195
  await Environment.saveToFile(response.data, targetPath);
5027
5196
  }
5028
5197
 
5029
5198
  /**
5030
- * Lists all batch jobs of the authenticated user.
5199
+ * List all batch jobs of the authenticated user.
5031
5200
  *
5032
5201
  * @async
5033
5202
  * @param {Array.<Job>} [oldJobs=[]] - A list of existing jobs to update.
@@ -5035,15 +5204,19 @@ class Connection {
5035
5204
  * @throws {Error}
5036
5205
  */
5037
5206
  async listJobs(oldJobs = []) {
5038
- let response = await this._get('/jobs');
5039
- let newJobs = response.data.jobs.map(newJob => {
5040
- let job = oldJobs.find(oldJob => oldJob.id === newJob.id);
5041
- if (!job) {
5042
- job = new Job(this, newJob.id);
5043
- }
5044
- return job.setAll(newJob);
5045
- });
5046
- return this._toResponseArray(newJobs, response.data);
5207
+ const pages = this.paginateJobs(null);
5208
+ const firstPage = await pages.nextPage(oldJobs);
5209
+ return firstPage;
5210
+ }
5211
+
5212
+ /**
5213
+ * Paginate through the batch jobs of the authenticated user.
5214
+ *
5215
+ * @param {?number} [limit=50] - The number of jobs per request/page as integer. If `null`, requests all jobs.
5216
+ * @returns {JobPages} A paged list of jobs.
5217
+ */
5218
+ paginateJobs(limit = 50) {
5219
+ return new JobPages(this, limit);
5047
5220
  }
5048
5221
 
5049
5222
  /**
@@ -5066,12 +5239,12 @@ class Connection {
5066
5239
  plan: plan,
5067
5240
  budget: budget
5068
5241
  });
5069
- let requestBody = this._normalizeUserProcess(process, additional);
5070
- let response = await this._post('/jobs', requestBody);
5242
+ const requestBody = this._normalizeUserProcess(process, additional);
5243
+ const response = await this._post('/jobs', requestBody);
5071
5244
  if (typeof response.headers['openeo-identifier'] !== 'string') {
5072
5245
  throw new Error("Response did not contain a Job ID. Job has likely been created, but may not show up yet.");
5073
5246
  }
5074
- let job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
5247
+ const job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
5075
5248
  if (this.capabilities().hasFeature('describeJob')) {
5076
5249
  return await job.describeJob();
5077
5250
  } else {
@@ -5088,12 +5261,12 @@ class Connection {
5088
5261
  * @throws {Error}
5089
5262
  */
5090
5263
  async getJob(id) {
5091
- let job = new Job(this, id);
5264
+ const job = new Job(this, id);
5092
5265
  return await job.describeJob();
5093
5266
  }
5094
5267
 
5095
5268
  /**
5096
- * Lists all secondary web services of the authenticated user.
5269
+ * List all secondary web services of the authenticated user.
5097
5270
  *
5098
5271
  * @async
5099
5272
  * @param {Array.<Service>} [oldServices=[]] - A list of existing services to update.
@@ -5101,15 +5274,18 @@ class Connection {
5101
5274
  * @throws {Error}
5102
5275
  */
5103
5276
  async listServices(oldServices = []) {
5104
- let response = await this._get('/services');
5105
- let newServices = response.data.services.map(newService => {
5106
- let service = oldServices.find(oldService => oldService.id === newService.id);
5107
- if (!service) {
5108
- service = new Service(this, newService.id);
5109
- }
5110
- return service.setAll(newService);
5111
- });
5112
- return this._toResponseArray(newServices, response.data);
5277
+ const pages = this.paginateServices(null);
5278
+ return await pages.nextPage(oldServices);
5279
+ }
5280
+
5281
+ /**
5282
+ * Paginate through the secondary web services of the authenticated user.
5283
+ *
5284
+ * @param {?number} [limit=50] - The number of services per request/page as integer. If `null` (default), requests all services.
5285
+ * @returns {ServicePages} A paged list of services.
5286
+ */
5287
+ paginateServices(limit = 50) {
5288
+ return new ServicePages(this, limit);
5113
5289
  }
5114
5290
 
5115
5291
  /**
@@ -5129,7 +5305,7 @@ class Connection {
5129
5305
  * @throws {Error}
5130
5306
  */
5131
5307
  async createService(process, type, title = null, description = null, enabled = true, configuration = {}, plan = null, budget = null, additional = {}) {
5132
- let requestBody = this._normalizeUserProcess(process, Object.assign({
5308
+ const requestBody = this._normalizeUserProcess(process, Object.assign({
5133
5309
  title: title,
5134
5310
  description: description,
5135
5311
  type: type,
@@ -5138,11 +5314,11 @@ class Connection {
5138
5314
  plan: plan,
5139
5315
  budget: budget
5140
5316
  }, additional));
5141
- let response = await this._post('/services', requestBody);
5317
+ const response = await this._post('/services', requestBody);
5142
5318
  if (typeof response.headers['openeo-identifier'] !== 'string') {
5143
5319
  throw new Error("Response did not contain a Service ID. Service has likely been created, but may not show up yet.");
5144
5320
  }
5145
- let service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
5321
+ const service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
5146
5322
  if (this.capabilities().hasFeature('describeService')) {
5147
5323
  return service.describeService();
5148
5324
  } else {
@@ -5159,26 +5335,10 @@ class Connection {
5159
5335
  * @throws {Error}
5160
5336
  */
5161
5337
  async getService(id) {
5162
- let service = new Service(this, id);
5338
+ const service = new Service(this, id);
5163
5339
  return await service.describeService();
5164
5340
  }
5165
5341
 
5166
- /**
5167
- * Adds additional response details to the array.
5168
- *
5169
- * Adds links and federation:missing.
5170
- *
5171
- * @protected
5172
- * @param {Array.<*>} arr
5173
- * @param {object.<string, *>} response
5174
- * @returns {ResponseArray}
5175
- */
5176
- _toResponseArray(arr, response) {
5177
- arr.links = Array.isArray(response.links) ? response.links : [];
5178
- arr['federation:missing'] = Array.isArray(response['federation:missing']) ? response['federation:missing'] : [];
5179
- return arr;
5180
- }
5181
-
5182
5342
  /**
5183
5343
  * Get the a link with the given rel type.
5184
5344
  *
@@ -5193,7 +5353,7 @@ class Connection {
5193
5353
  rel = [rel];
5194
5354
  }
5195
5355
  if (Array.isArray(links)) {
5196
- let link = links.find(l => Utils.isObject(l) && rel.includes(l.rel) && typeof l.href === 'string');
5356
+ const link = links.find(l => Utils.isObject(l) && rel.includes(l.rel) && typeof l.href === 'string');
5197
5357
  if (link) {
5198
5358
  return link.href;
5199
5359
  }
@@ -5229,7 +5389,7 @@ class Connection {
5229
5389
  return link;
5230
5390
  }
5231
5391
  try {
5232
- let url = new URL(link.href, baseUrl);
5392
+ const url = new URL(link.href, baseUrl);
5233
5393
  return Object.assign({}, link, {
5234
5394
  href: url.toString()
5235
5395
  });
@@ -5278,7 +5438,7 @@ class Connection {
5278
5438
  * @see https://github.com/axios/axios#request-config
5279
5439
  */
5280
5440
  async _post(path, body, responseType, abortController = null) {
5281
- let options = {
5441
+ const options = {
5282
5442
  method: 'post',
5283
5443
  responseType: responseType,
5284
5444
  url: path,
@@ -5350,7 +5510,7 @@ class Connection {
5350
5510
  * @throws {Error}
5351
5511
  */
5352
5512
  async download(url, authorize) {
5353
- let result = await this._send({
5513
+ const result = await this._send({
5354
5514
  method: 'get',
5355
5515
  responseType: Environment.getResponseType(),
5356
5516
  url: url,
@@ -5409,7 +5569,7 @@ class Connection {
5409
5569
  }
5410
5570
  try {
5411
5571
  let response = await axios(options);
5412
- let capabilities = this.capabilities();
5572
+ const capabilities = this.capabilities();
5413
5573
  if (capabilities) {
5414
5574
  response = capabilities.migrate(response);
5415
5575
  }
@@ -5433,7 +5593,7 @@ class Connection {
5433
5593
  // See: https://github.com/axios/axios/issues/815
5434
5594
  if (options.responseType === Environment.getResponseType()) {
5435
5595
  try {
5436
- let errorResponse = await Environment.handleErrorResponse(error);
5596
+ const errorResponse = await Environment.handleErrorResponse(error);
5437
5597
  throw enrichError(error, errorResponse);
5438
5598
  } catch (error2) {
5439
5599
  console.error(error2);
@@ -5909,9 +6069,26 @@ class Logs {
5909
6069
  * @type {Connection}
5910
6070
  */
5911
6071
  this.connection = connection;
6072
+ /**
6073
+ * @protected
6074
+ * @type {string}
6075
+ */
5912
6076
  this.endpoint = endpoint;
6077
+ /**
6078
+ * @protected
6079
+ * @type {string}
6080
+ */
5913
6081
  this.lastId = "";
6082
+ /**
6083
+ * @protected
6084
+ * @type {?string}
6085
+ */
5914
6086
  this.level = level;
6087
+ /**
6088
+ * @protected
6089
+ * @type {Set<string>}
6090
+ */
6091
+ this.missing = new Set();
5915
6092
  }
5916
6093
 
5917
6094
  /**
@@ -5928,6 +6105,19 @@ class Logs {
5928
6105
  return Array.isArray(response.logs) ? response.logs : [];
5929
6106
  }
5930
6107
 
6108
+ /**
6109
+ * Retrieves the backend identifiers that are (partially) missing in the logs.
6110
+ *
6111
+ * This is only filled after the first request using `nextLogs` or `next`.
6112
+ *
6113
+ * @returns {Array.<string>}
6114
+ * @see {Logs#nextLogs}
6115
+ * @see {Logs#next}
6116
+ */
6117
+ getMissingBackends() {
6118
+ return Array.from(this.missing);
6119
+ }
6120
+
5931
6121
  /**
5932
6122
  * Retrieves the next log entries since the last request.
5933
6123
  *
@@ -5955,6 +6145,9 @@ class Logs {
5955
6145
  response.data.logs = [];
5956
6146
  }
5957
6147
  response.data.links = Array.isArray(response.data.links) ? response.data.links : [];
6148
+ if (Array.isArray(response.data["federation:missing"])) {
6149
+ response.data["federation:missing"].forEach(backend => this.missing.add(backend));
6150
+ }
5958
6151
  return response.data;
5959
6152
  }
5960
6153
  }
@@ -6452,7 +6645,7 @@ class OpenEO {
6452
6645
  * @returns {string} Version number (according to SemVer).
6453
6646
  */
6454
6647
  static clientVersion() {
6455
- return "2.6.0";
6648
+ return "2.8.0";
6456
6649
  }
6457
6650
  }
6458
6651
  OpenEO.Environment = __webpack_require__(458);
@@ -6478,6 +6671,369 @@ module.exports = {
6478
6671
 
6479
6672
  /***/ }),
6480
6673
 
6674
+ /***/ 226:
6675
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
6676
+
6677
+ /* eslint-disable max-classes-per-file */
6678
+
6679
+ const Job = __webpack_require__(293);
6680
+ const Service = __webpack_require__(497);
6681
+ const UserFile = __webpack_require__(649);
6682
+ const UserProcess = __webpack_require__(806);
6683
+ const Utils = __webpack_require__(768);
6684
+ const StacMigrate = __webpack_require__(321);
6685
+ const FED_MISSING = 'federation:missing';
6686
+
6687
+ /**
6688
+ * A class to handle pagination of resources.
6689
+ *
6690
+ * @abstract
6691
+ */
6692
+ class Pages {
6693
+ /**
6694
+ * Creates an instance of Pages.
6695
+ *
6696
+ * @param {Connection} connection
6697
+ * @param {string} endpoint
6698
+ * @param {string} key
6699
+ * @param {Constructor} cls - Class
6700
+ * @param {object} [params={}]
6701
+ * @param {string} primaryKey
6702
+ */
6703
+ constructor(connection, endpoint, key, cls, params = {}, primaryKey = "id") {
6704
+ this.connection = connection;
6705
+ this.nextUrl = endpoint;
6706
+ this.key = key;
6707
+ this.primaryKey = primaryKey;
6708
+ this.cls = cls;
6709
+ if (!(params.limit > 0)) {
6710
+ delete params.limit;
6711
+ }
6712
+ this.params = params;
6713
+ }
6714
+
6715
+ /**
6716
+ * Returns true if there are more pages to fetch.
6717
+ *
6718
+ * @returns {boolean}
6719
+ */
6720
+ hasNextPage() {
6721
+ return this.nextUrl !== null;
6722
+ }
6723
+
6724
+ /**
6725
+ * Returns the next page of resources.
6726
+ *
6727
+ * @async
6728
+ * @param {Array.<object>} oldObjects - Existing objects to update, if any.
6729
+ * @param {boolean} [toArray=true] - Whether to return the objects as a simplified array or as an object with all information.
6730
+ * @returns {Array.<object>}
6731
+ * @throws {Error}
6732
+ */
6733
+ async nextPage(oldObjects = [], toArray = true) {
6734
+ // Request data from server
6735
+ const response = await this.connection._get(this.nextUrl, this.params);
6736
+ let data = response.data;
6737
+ // Check response
6738
+ if (!Utils.isObject(data)) {
6739
+ throw new Error(`Response is invalid, is not an object`);
6740
+ }
6741
+ if (!Array.isArray(data[this.key])) {
6742
+ throw new Error(`Response is invalid, '${this.key}' property is not an array`);
6743
+ }
6744
+
6745
+ // Update existing objects if needed
6746
+ let newObjects = data[this.key].map(updated => {
6747
+ let resource = oldObjects.find(old => old[this.primaryKey] === updated[this.primaryKey]);
6748
+ if (resource) {
6749
+ resource.setAll(updated);
6750
+ } else {
6751
+ resource = this._createObject(updated);
6752
+ }
6753
+ return resource;
6754
+ });
6755
+
6756
+ // Store objects in cache if needed
6757
+ newObjects = this._cache(newObjects);
6758
+
6759
+ // Add self link if missing
6760
+ data.links = this._ensureArray(data.links);
6761
+ const selfLink = this.connection._getLinkHref(data.links, 'self');
6762
+ if (!selfLink) {
6763
+ data.links.push({
6764
+ rel: 'self',
6765
+ href: this.nextUrl
6766
+ });
6767
+ }
6768
+
6769
+ // Check whether a next page is available
6770
+ this.nextUrl = this._getNextLink(response);
6771
+ // Don't append initial params to the next URL
6772
+ this.params = null;
6773
+
6774
+ // Either return as ResponseArray or full API response body
6775
+ if (toArray) {
6776
+ newObjects.links = data.links;
6777
+ newObjects[FED_MISSING] = this._ensureArray(data[FED_MISSING]);
6778
+ return newObjects;
6779
+ } else {
6780
+ data[this.key] = newObjects;
6781
+ return data;
6782
+ }
6783
+ }
6784
+
6785
+ /**
6786
+ * Ensures a variable is an array.
6787
+ *
6788
+ * @protected
6789
+ * @param {*} x
6790
+ * @returns {Array}
6791
+ */
6792
+ _ensureArray(x) {
6793
+ return Array.isArray(x) ? x : [];
6794
+ }
6795
+
6796
+ /**
6797
+ * Creates a facade for the object, if needed.
6798
+ *
6799
+ * @protected
6800
+ * @param {object} obj
6801
+ * @returns {object}
6802
+ */
6803
+ _createObject(obj) {
6804
+ if (this.cls) {
6805
+ const cls = this.cls;
6806
+ const newObj = new cls(this.connection, obj[this.primaryKey]);
6807
+ newObj.setAll(obj);
6808
+ return newObj;
6809
+ } else {
6810
+ return obj;
6811
+ }
6812
+ }
6813
+
6814
+ /**
6815
+ * Caches the plain objects if needed.
6816
+ *
6817
+ * @param {Array.<object>} objects
6818
+ * @returns {Array.<object>}
6819
+ */
6820
+ _cache(objects) {
6821
+ return objects;
6822
+ }
6823
+
6824
+ /**
6825
+ * Get the URL of the next page from a response.
6826
+ *
6827
+ * @protected
6828
+ * @param {AxiosResponse} response
6829
+ * @returns {string | null}
6830
+ */
6831
+ _getNextLink(response) {
6832
+ const links = this.connection.makeLinksAbsolute(response.data.links, response);
6833
+ return this.connection._getLinkHref(links, 'next');
6834
+ }
6835
+
6836
+ /**
6837
+ * Makes this class asynchronously iterable.
6838
+ *
6839
+ * @returns {AsyncIterator}
6840
+ */
6841
+ [Symbol.asyncIterator]() {
6842
+ return {
6843
+ self: this,
6844
+ /**
6845
+ * Get the next page of resources.
6846
+ *
6847
+ * @async
6848
+ * @returns {{done: boolean, value: Array.<object>}}
6849
+ */
6850
+ async next() {
6851
+ const done = !this.self.hasNextPage();
6852
+ let value;
6853
+ if (!done) {
6854
+ value = await this.self.nextPage();
6855
+ }
6856
+ return {
6857
+ done,
6858
+ value
6859
+ };
6860
+ }
6861
+ };
6862
+ }
6863
+ }
6864
+
6865
+ /**
6866
+ * Paginate through jobs.
6867
+ */
6868
+ class JobPages extends Pages {
6869
+ /**
6870
+ * Paginate through jobs.
6871
+ *
6872
+ * @param {Connection} connection
6873
+ * @param {?number} limit
6874
+ */
6875
+ constructor(connection, limit = null) {
6876
+ super(connection, "/jobs", "jobs", Job, {
6877
+ limit
6878
+ });
6879
+ }
6880
+ }
6881
+
6882
+ /**
6883
+ * Paginate through services.
6884
+ */
6885
+ class ServicePages extends Pages {
6886
+ /**
6887
+ * Paginate through services.
6888
+ *
6889
+ * @param {Connection} connection
6890
+ * @param {?number} limit
6891
+ */
6892
+ constructor(connection, limit = null) {
6893
+ super(connection, "/services", "services", Service, {
6894
+ limit
6895
+ });
6896
+ }
6897
+ }
6898
+
6899
+ /**
6900
+ * Paginate through user files.
6901
+ */
6902
+ class UserFilePages extends Pages {
6903
+ /**
6904
+ * Paginate through user files.
6905
+ *
6906
+ * @param {Connection} connection
6907
+ * @param {?number} limit
6908
+ */
6909
+ constructor(connection, limit = null) {
6910
+ super(connection, "/files", "files", UserFile, {
6911
+ limit
6912
+ }, "path");
6913
+ }
6914
+ }
6915
+
6916
+ /**
6917
+ * Paginate through processes.
6918
+ */
6919
+ class ProcessPages extends Pages {
6920
+ /**
6921
+ * Paginate through processes.
6922
+ *
6923
+ * @param {Connection} connection
6924
+ * @param {?number} limit
6925
+ * @param {?string} namespace
6926
+ */
6927
+ constructor(connection, limit = null, namespace = null) {
6928
+ if (!namespace) {
6929
+ namespace = 'backend';
6930
+ }
6931
+ let endpoint;
6932
+ let cls = null;
6933
+ if (namespace === 'user') {
6934
+ endpoint = '/process_graphs';
6935
+ cls = UserProcess;
6936
+ } else {
6937
+ endpoint = '/processes';
6938
+ if (namespace !== 'backend') {
6939
+ const normalized = connection.normalizeNamespace(namespace);
6940
+ endpoint += `/${normalized}`;
6941
+ }
6942
+ }
6943
+ super(connection, endpoint, "processes", cls, {
6944
+ limit
6945
+ });
6946
+ this.namespace = namespace;
6947
+ }
6948
+
6949
+ /**
6950
+ * Caches the objects to the ProcessRegistry.
6951
+ *
6952
+ * @param {Array.<object>} objects
6953
+ * @returns {Array.<object>}
6954
+ */
6955
+ _cache(objects) {
6956
+ const plainObjects = objects.map(p => typeof p.toJSON === 'function' ? p.toJSON() : p);
6957
+ this.connection.processes.addAll(plainObjects, this.namespace);
6958
+ if (!this.cls) {
6959
+ for (let i in objects) {
6960
+ objects[i] = this.connection.processes.get(objects[i].id, this.namespace);
6961
+ }
6962
+ }
6963
+ return objects;
6964
+ }
6965
+ }
6966
+
6967
+ /**
6968
+ * Paginate through collections.
6969
+ */
6970
+ class CollectionPages extends Pages {
6971
+ /**
6972
+ * Paginate through collections.
6973
+ *
6974
+ * @param {Connection} connection
6975
+ * @param {?number} limit
6976
+ */
6977
+ constructor(connection, limit = null) {
6978
+ super(connection, "/collections", "collections", null, {
6979
+ limit
6980
+ });
6981
+ }
6982
+
6983
+ /**
6984
+ * Migrates the STAC collection to the latest version.
6985
+ *
6986
+ * @param {object} obj
6987
+ * @returns {Collection}
6988
+ */
6989
+ _createObject(obj) {
6990
+ if (obj.stac_version) {
6991
+ return StacMigrate.collection(obj);
6992
+ }
6993
+ return obj;
6994
+ }
6995
+ }
6996
+
6997
+ /**
6998
+ * Paginate through collection items.
6999
+ */
7000
+ class ItemPages extends Pages {
7001
+ /**
7002
+ * Paginate through collection items.
7003
+ *
7004
+ * @param {Connection} connection
7005
+ * @param {string} collectionId
7006
+ * @param {object} params
7007
+ */
7008
+ constructor(connection, collectionId, params) {
7009
+ super(connection, `/collections/${collectionId}/items`, "features", null, params);
7010
+ }
7011
+
7012
+ /**
7013
+ * Migrates the STAC item to the latest version.
7014
+ *
7015
+ * @param {object} obj
7016
+ * @returns {Item}
7017
+ */
7018
+ _createObject(obj) {
7019
+ if (obj.stac_version) {
7020
+ return StacMigrate.item(obj);
7021
+ }
7022
+ return obj;
7023
+ }
7024
+ }
7025
+ module.exports = {
7026
+ Pages,
7027
+ CollectionPages,
7028
+ ItemPages,
7029
+ JobPages,
7030
+ ProcessPages,
7031
+ ServicePages,
7032
+ UserFilePages
7033
+ };
7034
+
7035
+ /***/ }),
7036
+
6481
7037
  /***/ 497:
6482
7038
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
6483
7039
 
@@ -6989,124 +7545,240 @@ module.exports = UserProcess;
6989
7545
 
6990
7546
  /***/ }),
6991
7547
 
6992
- /***/ 246:
6993
- /***/ (function(module, exports) {
6994
-
6995
- var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* global define */
6996
- (function (root, factory) {
6997
- /* istanbul ignore next */
6998
- if (true) {
6999
- !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
7000
- __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
7001
- (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
7002
- __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
7003
- } else {}
7004
- }(this, function () {
7005
-
7006
- var semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
7007
-
7008
- function indexOrEnd(str, q) {
7009
- return str.indexOf(q) === -1 ? str.length : str.indexOf(q);
7010
- }
7011
-
7012
- function split(v) {
7013
- var c = v.replace(/^v/, '').replace(/\+.*$/, '');
7014
- var patchIndex = indexOrEnd(c, '-');
7015
- var arr = c.substring(0, patchIndex).split('.');
7016
- arr.push(c.substring(patchIndex + 1));
7017
- return arr;
7018
- }
7019
-
7020
- function tryParse(v) {
7021
- return isNaN(Number(v)) ? v : Number(v);
7022
- }
7548
+ /***/ 385:
7549
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
7023
7550
 
7024
- function validate(version) {
7551
+ "use strict";
7552
+ // ESM COMPAT FLAG
7553
+ __webpack_require__.r(__webpack_exports__);
7554
+
7555
+ // EXPORTS
7556
+ __webpack_require__.d(__webpack_exports__, {
7557
+ compare: () => (/* reexport */ compare),
7558
+ compareVersions: () => (/* reexport */ compareVersions),
7559
+ satisfies: () => (/* reexport */ satisfies),
7560
+ validate: () => (/* reexport */ validate),
7561
+ validateStrict: () => (/* reexport */ validateStrict)
7562
+ });
7563
+
7564
+ ;// ./node_modules/compare-versions/lib/esm/utils.js
7565
+ const semver = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
7566
+ const validateAndParse = (version) => {
7025
7567
  if (typeof version !== 'string') {
7026
- throw new TypeError('Invalid argument expected string');
7568
+ throw new TypeError('Invalid argument expected string');
7027
7569
  }
7028
- if (!semver.test(version)) {
7029
- throw new Error('Invalid argument not valid semver (\''+version+'\' received)');
7570
+ const match = version.match(semver);
7571
+ if (!match) {
7572
+ throw new Error(`Invalid argument not valid semver ('${version}' received)`);
7030
7573
  }
7031
- }
7032
-
7033
- function compareVersions(v1, v2) {
7034
- [v1, v2].forEach(validate);
7035
-
7036
- var s1 = split(v1);
7037
- var s2 = split(v2);
7038
-
7039
- for (var i = 0; i < Math.max(s1.length - 1, s2.length - 1); i++) {
7040
- var n1 = parseInt(s1[i] || 0, 10);
7041
- var n2 = parseInt(s2[i] || 0, 10);
7042
-
7043
- if (n1 > n2) return 1;
7044
- if (n2 > n1) return -1;
7574
+ match.shift();
7575
+ return match;
7576
+ };
7577
+ const isWildcard = (s) => s === '*' || s === 'x' || s === 'X';
7578
+ const tryParse = (v) => {
7579
+ const n = parseInt(v, 10);
7580
+ return isNaN(n) ? v : n;
7581
+ };
7582
+ const forceType = (a, b) => typeof a !== typeof b ? [String(a), String(b)] : [a, b];
7583
+ const compareStrings = (a, b) => {
7584
+ if (isWildcard(a) || isWildcard(b))
7585
+ return 0;
7586
+ const [ap, bp] = forceType(tryParse(a), tryParse(b));
7587
+ if (ap > bp)
7588
+ return 1;
7589
+ if (ap < bp)
7590
+ return -1;
7591
+ return 0;
7592
+ };
7593
+ const compareSegments = (a, b) => {
7594
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
7595
+ const r = compareStrings(a[i] || '0', b[i] || '0');
7596
+ if (r !== 0)
7597
+ return r;
7045
7598
  }
7599
+ return 0;
7600
+ };
7601
+ //# sourceMappingURL=utils.js.map
7602
+ ;// ./node_modules/compare-versions/lib/esm/compareVersions.js
7046
7603
 
7047
- var sp1 = s1[s1.length - 1];
7048
- var sp2 = s2[s2.length - 1];
7049
-
7050
- if (sp1 && sp2) {
7051
- var p1 = sp1.split('.').map(tryParse);
7052
- var p2 = sp2.split('.').map(tryParse);
7053
-
7054
- for (i = 0; i < Math.max(p1.length, p2.length); i++) {
7055
- if (p1[i] === undefined || typeof p2[i] === 'string' && typeof p1[i] === 'number') return -1;
7056
- if (p2[i] === undefined || typeof p1[i] === 'string' && typeof p2[i] === 'number') return 1;
7057
-
7058
- if (p1[i] > p2[i]) return 1;
7059
- if (p2[i] > p1[i]) return -1;
7060
- }
7061
- } else if (sp1 || sp2) {
7062
- return sp1 ? -1 : 1;
7604
+ /**
7605
+ * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.
7606
+ * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`.
7607
+ * @param v1 - First version to compare
7608
+ * @param v2 - Second version to compare
7609
+ * @returns Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
7610
+ */
7611
+ const compareVersions = (v1, v2) => {
7612
+ // validate input and split into segments
7613
+ const n1 = validateAndParse(v1);
7614
+ const n2 = validateAndParse(v2);
7615
+ // pop off the patch
7616
+ const p1 = n1.pop();
7617
+ const p2 = n2.pop();
7618
+ // validate numbers
7619
+ const r = compareSegments(n1, n2);
7620
+ if (r !== 0)
7621
+ return r;
7622
+ // validate pre-release
7623
+ if (p1 && p2) {
7624
+ return compareSegments(p1.split('.'), p2.split('.'));
7625
+ }
7626
+ else if (p1 || p2) {
7627
+ return p1 ? -1 : 1;
7063
7628
  }
7064
-
7065
7629
  return 0;
7066
- };
7067
-
7068
- var allowedOperators = [
7069
- '>',
7070
- '>=',
7071
- '=',
7072
- '<',
7073
- '<='
7074
- ];
7630
+ };
7631
+ //# sourceMappingURL=compareVersions.js.map
7632
+ ;// ./node_modules/compare-versions/lib/esm/compare.js
7075
7633
 
7076
- var operatorResMap = {
7634
+ /**
7635
+ * Compare [semver](https://semver.org/) version strings using the specified operator.
7636
+ *
7637
+ * @param v1 First version to compare
7638
+ * @param v2 Second version to compare
7639
+ * @param operator Allowed arithmetic operator to use
7640
+ * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise.
7641
+ *
7642
+ * @example
7643
+ * ```
7644
+ * compare('10.1.8', '10.0.4', '>'); // return true
7645
+ * compare('10.0.1', '10.0.1', '='); // return true
7646
+ * compare('10.1.1', '10.2.2', '<'); // return true
7647
+ * compare('10.1.1', '10.2.2', '<='); // return true
7648
+ * compare('10.1.1', '10.2.2', '>='); // return false
7649
+ * ```
7650
+ */
7651
+ const compare = (v1, v2, operator) => {
7652
+ // validate input operator
7653
+ assertValidOperator(operator);
7654
+ // since result of compareVersions can only be -1 or 0 or 1
7655
+ // a simple map can be used to replace switch
7656
+ const res = compareVersions(v1, v2);
7657
+ return operatorResMap[operator].includes(res);
7658
+ };
7659
+ const operatorResMap = {
7077
7660
  '>': [1],
7078
7661
  '>=': [0, 1],
7079
7662
  '=': [0],
7080
7663
  '<=': [-1, 0],
7081
- '<': [-1]
7082
- };
7083
-
7084
- function validateOperator(op) {
7664
+ '<': [-1],
7665
+ '!=': [-1, 1],
7666
+ };
7667
+ const allowedOperators = Object.keys(operatorResMap);
7668
+ const assertValidOperator = (op) => {
7085
7669
  if (typeof op !== 'string') {
7086
- throw new TypeError('Invalid operator type, expected string but got ' + typeof op);
7670
+ throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`);
7087
7671
  }
7088
7672
  if (allowedOperators.indexOf(op) === -1) {
7089
- throw new TypeError('Invalid operator, expected one of ' + allowedOperators.join('|'));
7673
+ throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`);
7090
7674
  }
7091
- }
7675
+ };
7676
+ //# sourceMappingURL=compare.js.map
7677
+ ;// ./node_modules/compare-versions/lib/esm/satisfies.js
7092
7678
 
7093
- compareVersions.validate = function(version) {
7094
- return typeof version === 'string' && semver.test(version);
7095
- }
7096
7679
 
7097
- compareVersions.compare = function (v1, v2, operator) {
7098
- // Validate operator
7099
- validateOperator(operator);
7680
+ /**
7681
+ * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range.
7682
+ *
7683
+ * @param version Version number to match
7684
+ * @param range Range pattern for version
7685
+ * @returns `true` if the version number is within the range, `false` otherwise.
7686
+ *
7687
+ * @example
7688
+ * ```
7689
+ * satisfies('1.1.0', '^1.0.0'); // return true
7690
+ * satisfies('1.1.0', '~1.0.0'); // return false
7691
+ * ```
7692
+ */
7693
+ const satisfies = (version, range) => {
7694
+ // clean input
7695
+ range = range.replace(/([><=]+)\s+/g, '$1');
7696
+ // handle multiple comparators
7697
+ if (range.includes('||')) {
7698
+ return range.split('||').some((r) => satisfies(version, r));
7699
+ }
7700
+ else if (range.includes(' - ')) {
7701
+ const [a, b] = range.split(' - ', 2);
7702
+ return satisfies(version, `>=${a} <=${b}`);
7703
+ }
7704
+ else if (range.includes(' ')) {
7705
+ return range
7706
+ .trim()
7707
+ .replace(/\s{2,}/g, ' ')
7708
+ .split(' ')
7709
+ .every((r) => satisfies(version, r));
7710
+ }
7711
+ // if no range operator then "="
7712
+ const m = range.match(/^([<>=~^]+)/);
7713
+ const op = m ? m[1] : '=';
7714
+ // if gt/lt/eq then operator compare
7715
+ if (op !== '^' && op !== '~')
7716
+ return compare(version, range, op);
7717
+ // else range of either "~" or "^" is assumed
7718
+ const [v1, v2, v3, , vp] = validateAndParse(version);
7719
+ const [r1, r2, r3, , rp] = validateAndParse(range);
7720
+ const v = [v1, v2, v3];
7721
+ const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x'];
7722
+ // validate pre-release
7723
+ if (rp) {
7724
+ if (!vp)
7725
+ return false;
7726
+ if (compareSegments(v, r) !== 0)
7727
+ return false;
7728
+ if (compareSegments(vp.split('.'), rp.split('.')) === -1)
7729
+ return false;
7730
+ }
7731
+ // first non-zero number
7732
+ const nonZero = r.findIndex((v) => v !== '0') + 1;
7733
+ // pointer to where segments can be >=
7734
+ const i = op === '~' ? 2 : nonZero > 1 ? nonZero : 1;
7735
+ // before pointer must be equal
7736
+ if (compareSegments(v.slice(0, i), r.slice(0, i)) !== 0)
7737
+ return false;
7738
+ // after pointer must be >=
7739
+ if (compareSegments(v.slice(i), r.slice(i)) === -1)
7740
+ return false;
7741
+ return true;
7742
+ };
7743
+ //# sourceMappingURL=satisfies.js.map
7744
+ ;// ./node_modules/compare-versions/lib/esm/validate.js
7745
+
7746
+ /**
7747
+ * Validate [semver](https://semver.org/) version strings.
7748
+ *
7749
+ * @param version Version number to validate
7750
+ * @returns `true` if the version number is a valid semver version number, `false` otherwise.
7751
+ *
7752
+ * @example
7753
+ * ```
7754
+ * validate('1.0.0-rc.1'); // return true
7755
+ * validate('1.0-rc.1'); // return false
7756
+ * validate('foo'); // return false
7757
+ * ```
7758
+ */
7759
+ const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version);
7760
+ /**
7761
+ * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges.
7762
+ *
7763
+ * @param version Version number to validate
7764
+ * @returns `true` if the version number is a valid semver version number `false` otherwise
7765
+ *
7766
+ * @example
7767
+ * ```
7768
+ * validate('1.0.0-rc.1'); // return true
7769
+ * validate('1.0-rc.1'); // return false
7770
+ * validate('foo'); // return false
7771
+ * ```
7772
+ */
7773
+ const validateStrict = (version) => typeof version === 'string' &&
7774
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version);
7775
+ //# sourceMappingURL=validate.js.map
7776
+ ;// ./node_modules/compare-versions/lib/esm/index.js
7777
+
7100
7778
 
7101
- // since result of compareVersions can only be -1 or 0 or 1
7102
- // a simple map can be used to replace switch
7103
- var res = compareVersions(v1, v2);
7104
- return operatorResMap[operator].indexOf(res) > -1;
7105
- }
7106
7779
 
7107
- return compareVersions;
7108
- }));
7109
7780
 
7781
+ //# sourceMappingURL=index.js.map
7110
7782
 
7111
7783
  /***/ }),
7112
7784
 
@@ -7233,6 +7905,35 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__742__;
7233
7905
  /******/ }
7234
7906
  /******/
7235
7907
  /************************************************************************/
7908
+ /******/ /* webpack/runtime/define property getters */
7909
+ /******/ (() => {
7910
+ /******/ // define getter functions for harmony exports
7911
+ /******/ __webpack_require__.d = (exports, definition) => {
7912
+ /******/ for(var key in definition) {
7913
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
7914
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
7915
+ /******/ }
7916
+ /******/ }
7917
+ /******/ };
7918
+ /******/ })();
7919
+ /******/
7920
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
7921
+ /******/ (() => {
7922
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
7923
+ /******/ })();
7924
+ /******/
7925
+ /******/ /* webpack/runtime/make namespace object */
7926
+ /******/ (() => {
7927
+ /******/ // define __esModule on exports
7928
+ /******/ __webpack_require__.r = (exports) => {
7929
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
7930
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7931
+ /******/ }
7932
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
7933
+ /******/ };
7934
+ /******/ })();
7935
+ /******/
7936
+ /************************************************************************/
7236
7937
  /******/
7237
7938
  /******/ // startup
7238
7939
  /******/ // Load entry module and return exports