@openeo/js-client 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,15 @@ 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
+ return Array.isArray(this.data.federation) ? this.data.federation : [];
4232
+ }
4233
+
4104
4234
  /**
4105
4235
  * Lists all supported features.
4106
4236
  *
@@ -4193,6 +4323,14 @@ const UserProcess = __webpack_require__(806);
4193
4323
  const Service = __webpack_require__(497);
4194
4324
  const Builder = __webpack_require__(425);
4195
4325
  const BuilderNode = __webpack_require__(804);
4326
+ const {
4327
+ CollectionPages,
4328
+ ItemPages,
4329
+ JobPages,
4330
+ ProcessPages,
4331
+ ServicePages,
4332
+ UserFilePages
4333
+ } = __webpack_require__(226);
4196
4334
  const CONFORMANCE_RELS = ['conformance', 'http://www.opengis.net/def/rel/ogc/1.0/conformance'];
4197
4335
 
4198
4336
  /**
@@ -4277,13 +4415,13 @@ class Connection {
4277
4415
  * @throws {Error}
4278
4416
  */
4279
4417
  async init() {
4280
- let response = await this._get('/');
4281
- let data = Object.assign({}, response.data);
4418
+ const response = await this._get('/');
4419
+ const data = Object.assign({}, response.data);
4282
4420
  data.links = this.makeLinksAbsolute(data.links, response);
4283
4421
  if (!Array.isArray(data.conformsTo) && Array.isArray(data.links)) {
4284
- let conformanceLink = this._getLinkHref(data.links, CONFORMANCE_RELS);
4422
+ const conformanceLink = this._getLinkHref(data.links, CONFORMANCE_RELS);
4285
4423
  if (conformanceLink) {
4286
- let response2 = await this._get(conformanceLink);
4424
+ const response2 = await this._get(conformanceLink);
4287
4425
  if (Utils.isObject(response2.data) && Array.isArray(response2.data.conformsTo)) {
4288
4426
  data.conformsTo = response2.data.conformsTo;
4289
4427
  }
@@ -4304,10 +4442,10 @@ class Connection {
4304
4442
  if (this.processes.count() === 0) {
4305
4443
  return;
4306
4444
  }
4307
- let promises = this.processes.namespaces().map(namespace => {
4445
+ const promises = this.processes.namespaces().map(namespace => {
4308
4446
  let fn = () => Promise.resolve();
4309
4447
  if (namespace === 'user') {
4310
- let userProcesses = this.processes.namespace('user');
4448
+ const userProcesses = this.processes.namespace('user');
4311
4449
  if (!this.isAuthenticated()) {
4312
4450
  fn = () => this.processes.remove(null, 'user') ? Promise.resolve() : Promise.reject(new Error("Can't clear user processes"));
4313
4451
  } else if (this.capabilities().hasFeature('listUserProcesses')) {
@@ -4356,7 +4494,7 @@ class Connection {
4356
4494
  * @throws {Error}
4357
4495
  */
4358
4496
  async listFileTypes() {
4359
- let response = await this._get('/file_formats');
4497
+ const response = await this._get('/file_formats');
4360
4498
  return new FileTypes(response.data);
4361
4499
  }
4362
4500
 
@@ -4368,7 +4506,7 @@ class Connection {
4368
4506
  * @throws {Error}
4369
4507
  */
4370
4508
  async listServiceTypes() {
4371
- let response = await this._get('/service_types');
4509
+ const response = await this._get('/service_types');
4372
4510
  return response.data;
4373
4511
  }
4374
4512
 
@@ -4380,7 +4518,7 @@ class Connection {
4380
4518
  * @throws {Error}
4381
4519
  */
4382
4520
  async listUdfRuntimes() {
4383
- let response = await this._get('/udf_runtimes');
4521
+ const response = await this._get('/udf_runtimes');
4384
4522
  return response.data;
4385
4523
  }
4386
4524
 
@@ -4388,22 +4526,27 @@ class Connection {
4388
4526
  * List all collections available on the back-end.
4389
4527
  *
4390
4528
  * The collections returned always comply to the latest STAC version (currently 1.0.0).
4529
+ * This function adds a self link to the response if not present.
4391
4530
  *
4392
4531
  * @async
4393
4532
  * @returns {Promise<Collections>} A response compatible to the API specification.
4394
4533
  * @throws {Error}
4395
4534
  */
4396
4535
  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;
4536
+ const pages = this.paginateCollections(null);
4537
+ return await pages.nextPage([], false);
4538
+ }
4539
+
4540
+ /**
4541
+ * Paginate through the collections available on the back-end.
4542
+ *
4543
+ * The collections returned always comply to the latest STAC version (currently 1.0.0).
4544
+ *
4545
+ * @param {?number} [limit=50] - The number of collections per request/page as integer. If `null`, requests all collections.
4546
+ * @returns {CollectionPages} A paged list of collections.
4547
+ */
4548
+ paginateCollections(limit = 50) {
4549
+ return new CollectionPages(this, limit);
4407
4550
  }
4408
4551
 
4409
4552
  /**
@@ -4417,7 +4560,7 @@ class Connection {
4417
4560
  * @throws {Error}
4418
4561
  */
4419
4562
  async describeCollection(collectionId) {
4420
- let response = await this._get('/collections/' + collectionId);
4563
+ const response = await this._get('/collections/' + collectionId);
4421
4564
  if (response.data.stac_version) {
4422
4565
  return StacMigrate.collection(response.data);
4423
4566
  } else {
@@ -4426,13 +4569,12 @@ class Connection {
4426
4569
  }
4427
4570
 
4428
4571
  /**
4429
- * Loads items for a specific image collection.
4572
+ * Paginate through items for a specific collection.
4573
+ *
4430
4574
  * May not be available for all collections.
4431
4575
  *
4432
4576
  * The items returned always comply to the latest STAC version (currently 1.0.0).
4433
4577
  *
4434
- * This is an experimental API and is subject to change.
4435
- *
4436
4578
  * @async
4437
4579
  * @param {string} collectionId - Collection ID to request items for.
4438
4580
  * @param {?Array.<number>} [spatialExtent=null] - Limits the items to the given bounding box in WGS84:
@@ -4445,46 +4587,28 @@ class Connection {
4445
4587
  * each must be either an RFC 3339 compatible string or a Date object.
4446
4588
  * Also supports open intervals by setting one of the boundaries to `null`, but never both.
4447
4589
  * @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.
4590
+ * @returns {Promise<ItemPages>} A response compatible to the API specification.
4449
4591
  * @throws {Error}
4450
4592
  */
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('/');
4469
- }
4470
- if (limit > 0) {
4471
- params.limit = limit;
4593
+ listCollectionItems(collectionId, spatialExtent = null, temporalExtent = null, limit = null) {
4594
+ let params = {};
4595
+ if (Array.isArray(spatialExtent)) {
4596
+ params.bbox = spatialExtent.join(',');
4597
+ }
4598
+ if (Array.isArray(temporalExtent)) {
4599
+ params.datetime = temporalExtent.map(e => {
4600
+ if (e instanceof Date) {
4601
+ return e.toISOString();
4602
+ } else if (typeof e === 'string') {
4603
+ return e;
4472
4604
  }
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');
4605
+ return '..'; // Open date range
4606
+ }).join('/');
4607
+ }
4608
+ if (limit > 0) {
4609
+ params.limit = limit;
4487
4610
  }
4611
+ return new ItemPages(this, collectionId, params, limit);
4488
4612
  }
4489
4613
 
4490
4614
  /**
@@ -4507,7 +4631,7 @@ class Connection {
4507
4631
  }
4508
4632
 
4509
4633
  /**
4510
- * List processes available on the back-end.
4634
+ * List all processes available on the back-end.
4511
4635
  *
4512
4636
  * Requests pre-defined processes by default.
4513
4637
  * Set the namespace parameter to request processes from a specific namespace.
@@ -4515,27 +4639,33 @@ class Connection {
4515
4639
  * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given.
4516
4640
  * The namespaces are then listed in the property `namespaces`.
4517
4641
  *
4642
+ * This function adds a self link to the response if not present.
4643
+ *
4518
4644
  * @async
4519
4645
  * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
4520
4646
  * @returns {Promise<Processes>} - A response compatible to the API specification.
4521
4647
  * @throws {Error}
4522
4648
  */
4523
4649
  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
- }
4650
+ const pages = this.paginateProcesses(namespace);
4651
+ return await pages.nextPage([], false);
4652
+ }
4532
4653
 
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
- });
4654
+ /**
4655
+ * Paginate through the processes available on the back-end.
4656
+ *
4657
+ * Requests pre-defined processes by default.
4658
+ * Set the namespace parameter to request processes from a specific namespace.
4659
+ *
4660
+ * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given.
4661
+ * The namespaces are then listed in the property `namespaces`.
4662
+ *
4663
+ * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL!
4664
+ * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes.
4665
+ * @returns {ProcessPages} A paged list of processes.
4666
+ */
4667
+ paginateProcesses(namespace = null, limit = 50) {
4668
+ return new ProcessPages(this, limit, namespace);
4539
4669
  }
4540
4670
 
4541
4671
  /**
@@ -4555,7 +4685,7 @@ class Connection {
4555
4685
  if (namespace === 'backend') {
4556
4686
  await this.listProcesses();
4557
4687
  } else {
4558
- let response = await this._get(`/processes/${this.normalizeNamespace(namespace)}/${processId}`);
4688
+ const response = await this._get(`/processes/${this.normalizeNamespace(namespace)}/${processId}`);
4559
4689
  if (!Utils.isObject(response.data) || typeof response.data.id !== 'string') {
4560
4690
  throw new Error('Invalid response received for process');
4561
4691
  }
@@ -4591,15 +4721,15 @@ class Connection {
4591
4721
  return this.authProviderList;
4592
4722
  }
4593
4723
  this.authProviderList = [];
4594
- let cap = this.capabilities();
4724
+ const cap = this.capabilities();
4595
4725
 
4596
4726
  // Add OIDC providers
4597
4727
  if (cap.hasFeature('authenticateOIDC')) {
4598
- let res = await this._get('/credentials/oidc');
4599
- let oidcFactory = this.getOidcProviderFactory();
4728
+ const res = await this._get('/credentials/oidc');
4729
+ const oidcFactory = this.getOidcProviderFactory();
4600
4730
  if (Utils.isObject(res.data) && Array.isArray(res.data.providers) && typeof oidcFactory === 'function') {
4601
4731
  for (let i in res.data.providers) {
4602
- let obj = oidcFactory(res.data.providers[i]);
4732
+ const obj = oidcFactory(res.data.providers[i]);
4603
4733
  if (obj instanceof AuthProvider) {
4604
4734
  this.authProviderList.push(obj);
4605
4735
  }
@@ -4677,7 +4807,7 @@ class Connection {
4677
4807
  * @see Connection#listAuthProviders
4678
4808
  */
4679
4809
  async authenticateBasic(username, password) {
4680
- let basic = new BasicProvider(this);
4810
+ const basic = new BasicProvider(this);
4681
4811
  await basic.login(username, password);
4682
4812
  }
4683
4813
 
@@ -4770,7 +4900,7 @@ class Connection {
4770
4900
  * @returns {AuthProvider}
4771
4901
  */
4772
4902
  setAuthToken(type, providerId, token) {
4773
- let provider = new AuthProvider(type, this, {
4903
+ const provider = new AuthProvider(type, this, {
4774
4904
  id: providerId,
4775
4905
  title: "Custom",
4776
4906
  description: ""
@@ -4790,21 +4920,30 @@ class Connection {
4790
4920
  * @throws {Error}
4791
4921
  */
4792
4922
  async describeAccount() {
4793
- let response = await this._get('/me');
4923
+ const response = await this._get('/me');
4794
4924
  return response.data;
4795
4925
  }
4796
4926
 
4797
4927
  /**
4798
- * Lists all files from the user workspace.
4928
+ * List all files from the user workspace.
4799
4929
  *
4800
4930
  * @async
4801
4931
  * @returns {Promise<ResponseArray.<UserFile>>} A list of files.
4802
4932
  * @throws {Error}
4803
4933
  */
4804
4934
  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);
4935
+ const pages = this.paginateFiles(null);
4936
+ return await pages.nextPage();
4937
+ }
4938
+
4939
+ /**
4940
+ * Paginate through the files from the user workspace.
4941
+ *
4942
+ * @param {?number} [limit=50] - The number of files per request/page as integer. If `null`, requests all files.
4943
+ * @returns {ServicePages} A paged list of files.
4944
+ */
4945
+ paginateFiles(limit = 50) {
4946
+ return new UserFilePages(this, limit);
4808
4947
  }
4809
4948
 
4810
4949
  /**
@@ -4835,7 +4974,7 @@ class Connection {
4835
4974
  if (targetPath === null) {
4836
4975
  targetPath = Environment.fileNameForUpload(source);
4837
4976
  }
4838
- let file = await this.getFile(targetPath);
4977
+ const file = await this.getFile(targetPath);
4839
4978
  return await file.uploadFile(source, statusCallback, abortController);
4840
4979
  }
4841
4980
 
@@ -4881,20 +5020,22 @@ class Connection {
4881
5020
  *
4882
5021
  * @async
4883
5022
  * @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.
5023
+ * @returns {Promise<ValidationResult>} errors - A list of API compatible error objects. A valid process returns an empty list.
4885
5024
  * @throws {Error}
4886
5025
  */
4887
5026
  async validateProcess(process) {
4888
- let response = await this._post('/validation', this._normalizeUserProcess(process).process);
5027
+ const response = await this._post('/validation', this._normalizeUserProcess(process).process);
4889
5028
  if (Array.isArray(response.data.errors)) {
4890
- return response.data.errors;
5029
+ const errors = response.data.errors;
5030
+ errors['federation:backends'] = Array.isArray(response.data['federation:missing']) ? response.data['federation:missing'] : [];
5031
+ return errors;
4891
5032
  } else {
4892
5033
  throw new Error("Invalid validation response received.");
4893
5034
  }
4894
5035
  }
4895
5036
 
4896
5037
  /**
4897
- * Lists all user-defined processes of the authenticated user.
5038
+ * List all user-defined processes of the authenticated user.
4898
5039
  *
4899
5040
  * @async
4900
5041
  * @param {Array.<UserProcess>} [oldProcesses=[]] - A list of existing user-defined processes to update.
@@ -4902,27 +5043,18 @@ class Connection {
4902
5043
  * @throws {Error}
4903
5044
  */
4904
5045
  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
- });
5046
+ const pages = this.paginateUserProcesses(null);
5047
+ return await pages.nextPage(oldProcesses);
5048
+ }
4921
5049
 
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);
5050
+ /**
5051
+ * Paginates through the user-defined processes of the authenticated user.
5052
+ *
5053
+ * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes.
5054
+ * @returns {ProcessPages} A paged list of user-defined processes.
5055
+ */
5056
+ paginateUserProcesses(limit = 50) {
5057
+ return this.paginateProcesses('user', limit);
4926
5058
  }
4927
5059
 
4928
5060
  /**
@@ -4935,7 +5067,7 @@ class Connection {
4935
5067
  * @throws {Error}
4936
5068
  */
4937
5069
  async setUserProcess(id, process) {
4938
- let pg = new UserProcess(this, id);
5070
+ const pg = new UserProcess(this, id);
4939
5071
  return await pg.replaceUserProcess(process);
4940
5072
  }
4941
5073
 
@@ -4948,7 +5080,7 @@ class Connection {
4948
5080
  * @throws {Error}
4949
5081
  */
4950
5082
  async getUserProcess(id) {
4951
- let pg = new UserProcess(this, id);
5083
+ const pg = new UserProcess(this, id);
4952
5084
  return await pg.describeUserProcess();
4953
5085
  }
4954
5086
 
@@ -4966,12 +5098,12 @@ class Connection {
4966
5098
  * @returns {Promise<SyncResult>} - An object with the data and some metadata.
4967
5099
  */
4968
5100
  async computeResult(process, plan = null, budget = null, abortController = null, additional = {}) {
4969
- let requestBody = this._normalizeUserProcess(process, Object.assign({}, additional, {
5101
+ const requestBody = this._normalizeUserProcess(process, Object.assign({}, additional, {
4970
5102
  plan: plan,
4971
5103
  budget: budget
4972
5104
  }));
4973
- let response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
4974
- let syncResult = {
5105
+ const response = await this._post('/result', requestBody, Environment.getResponseType(), abortController);
5106
+ const syncResult = {
4975
5107
  data: response.data,
4976
5108
  costs: null,
4977
5109
  type: null,
@@ -4983,15 +5115,15 @@ class Connection {
4983
5115
  if (typeof response.headers['content-type'] === 'string') {
4984
5116
  syncResult.type = response.headers['content-type'];
4985
5117
  }
4986
- let links = Array.isArray(response.headers.link) ? response.headers.link : [response.headers.link];
5118
+ const links = Array.isArray(response.headers.link) ? response.headers.link : [response.headers.link];
4987
5119
  for (let link of links) {
4988
5120
  if (typeof link !== 'string') {
4989
5121
  continue;
4990
5122
  }
4991
- let logs = link.match(/^<([^>]+)>;\s?rel="monitor"/i);
5123
+ const logs = link.match(/^<([^>]+)>;\s?rel="monitor"/i);
4992
5124
  if (Array.isArray(logs) && logs.length > 1) {
4993
5125
  try {
4994
- let logsResponse = await this._get(logs[1]);
5126
+ const logsResponse = await this._get(logs[1]);
4995
5127
  if (Utils.isObject(logsResponse.data) && Array.isArray(logsResponse.data.logs)) {
4996
5128
  syncResult.logs = logsResponse.data.logs;
4997
5129
  }
@@ -5021,13 +5153,13 @@ class Connection {
5021
5153
  * @throws {Error}
5022
5154
  */
5023
5155
  async downloadResult(process, targetPath, plan = null, budget = null, abortController = null) {
5024
- let response = await this.computeResult(process, plan, budget, abortController);
5156
+ const response = await this.computeResult(process, plan, budget, abortController);
5025
5157
  // @ts-ignore
5026
5158
  await Environment.saveToFile(response.data, targetPath);
5027
5159
  }
5028
5160
 
5029
5161
  /**
5030
- * Lists all batch jobs of the authenticated user.
5162
+ * List all batch jobs of the authenticated user.
5031
5163
  *
5032
5164
  * @async
5033
5165
  * @param {Array.<Job>} [oldJobs=[]] - A list of existing jobs to update.
@@ -5035,15 +5167,19 @@ class Connection {
5035
5167
  * @throws {Error}
5036
5168
  */
5037
5169
  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);
5170
+ const pages = this.paginateJobs(null);
5171
+ const firstPage = await pages.nextPage(oldJobs);
5172
+ return firstPage;
5173
+ }
5174
+
5175
+ /**
5176
+ * Paginate through the batch jobs of the authenticated user.
5177
+ *
5178
+ * @param {?number} [limit=50] - The number of jobs per request/page as integer. If `null`, requests all jobs.
5179
+ * @returns {JobPages} A paged list of jobs.
5180
+ */
5181
+ paginateJobs(limit = 50) {
5182
+ return new JobPages(this, limit);
5047
5183
  }
5048
5184
 
5049
5185
  /**
@@ -5066,12 +5202,12 @@ class Connection {
5066
5202
  plan: plan,
5067
5203
  budget: budget
5068
5204
  });
5069
- let requestBody = this._normalizeUserProcess(process, additional);
5070
- let response = await this._post('/jobs', requestBody);
5205
+ const requestBody = this._normalizeUserProcess(process, additional);
5206
+ const response = await this._post('/jobs', requestBody);
5071
5207
  if (typeof response.headers['openeo-identifier'] !== 'string') {
5072
5208
  throw new Error("Response did not contain a Job ID. Job has likely been created, but may not show up yet.");
5073
5209
  }
5074
- let job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
5210
+ const job = new Job(this, response.headers['openeo-identifier']).setAll(requestBody);
5075
5211
  if (this.capabilities().hasFeature('describeJob')) {
5076
5212
  return await job.describeJob();
5077
5213
  } else {
@@ -5088,12 +5224,12 @@ class Connection {
5088
5224
  * @throws {Error}
5089
5225
  */
5090
5226
  async getJob(id) {
5091
- let job = new Job(this, id);
5227
+ const job = new Job(this, id);
5092
5228
  return await job.describeJob();
5093
5229
  }
5094
5230
 
5095
5231
  /**
5096
- * Lists all secondary web services of the authenticated user.
5232
+ * List all secondary web services of the authenticated user.
5097
5233
  *
5098
5234
  * @async
5099
5235
  * @param {Array.<Service>} [oldServices=[]] - A list of existing services to update.
@@ -5101,15 +5237,18 @@ class Connection {
5101
5237
  * @throws {Error}
5102
5238
  */
5103
5239
  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);
5240
+ const pages = this.paginateServices(null);
5241
+ return await pages.nextPage(oldServices);
5242
+ }
5243
+
5244
+ /**
5245
+ * Paginate through the secondary web services of the authenticated user.
5246
+ *
5247
+ * @param {?number} [limit=50] - The number of services per request/page as integer. If `null` (default), requests all services.
5248
+ * @returns {ServicePages} A paged list of services.
5249
+ */
5250
+ paginateServices(limit = 50) {
5251
+ return new ServicePages(this, limit);
5113
5252
  }
5114
5253
 
5115
5254
  /**
@@ -5129,7 +5268,7 @@ class Connection {
5129
5268
  * @throws {Error}
5130
5269
  */
5131
5270
  async createService(process, type, title = null, description = null, enabled = true, configuration = {}, plan = null, budget = null, additional = {}) {
5132
- let requestBody = this._normalizeUserProcess(process, Object.assign({
5271
+ const requestBody = this._normalizeUserProcess(process, Object.assign({
5133
5272
  title: title,
5134
5273
  description: description,
5135
5274
  type: type,
@@ -5138,11 +5277,11 @@ class Connection {
5138
5277
  plan: plan,
5139
5278
  budget: budget
5140
5279
  }, additional));
5141
- let response = await this._post('/services', requestBody);
5280
+ const response = await this._post('/services', requestBody);
5142
5281
  if (typeof response.headers['openeo-identifier'] !== 'string') {
5143
5282
  throw new Error("Response did not contain a Service ID. Service has likely been created, but may not show up yet.");
5144
5283
  }
5145
- let service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
5284
+ const service = new Service(this, response.headers['openeo-identifier']).setAll(requestBody);
5146
5285
  if (this.capabilities().hasFeature('describeService')) {
5147
5286
  return service.describeService();
5148
5287
  } else {
@@ -5159,26 +5298,10 @@ class Connection {
5159
5298
  * @throws {Error}
5160
5299
  */
5161
5300
  async getService(id) {
5162
- let service = new Service(this, id);
5301
+ const service = new Service(this, id);
5163
5302
  return await service.describeService();
5164
5303
  }
5165
5304
 
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
5305
  /**
5183
5306
  * Get the a link with the given rel type.
5184
5307
  *
@@ -5193,7 +5316,7 @@ class Connection {
5193
5316
  rel = [rel];
5194
5317
  }
5195
5318
  if (Array.isArray(links)) {
5196
- let link = links.find(l => Utils.isObject(l) && rel.includes(l.rel) && typeof l.href === 'string');
5319
+ const link = links.find(l => Utils.isObject(l) && rel.includes(l.rel) && typeof l.href === 'string');
5197
5320
  if (link) {
5198
5321
  return link.href;
5199
5322
  }
@@ -5229,7 +5352,7 @@ class Connection {
5229
5352
  return link;
5230
5353
  }
5231
5354
  try {
5232
- let url = new URL(link.href, baseUrl);
5355
+ const url = new URL(link.href, baseUrl);
5233
5356
  return Object.assign({}, link, {
5234
5357
  href: url.toString()
5235
5358
  });
@@ -5278,7 +5401,7 @@ class Connection {
5278
5401
  * @see https://github.com/axios/axios#request-config
5279
5402
  */
5280
5403
  async _post(path, body, responseType, abortController = null) {
5281
- let options = {
5404
+ const options = {
5282
5405
  method: 'post',
5283
5406
  responseType: responseType,
5284
5407
  url: path,
@@ -5350,7 +5473,7 @@ class Connection {
5350
5473
  * @throws {Error}
5351
5474
  */
5352
5475
  async download(url, authorize) {
5353
- let result = await this._send({
5476
+ const result = await this._send({
5354
5477
  method: 'get',
5355
5478
  responseType: Environment.getResponseType(),
5356
5479
  url: url,
@@ -5409,7 +5532,7 @@ class Connection {
5409
5532
  }
5410
5533
  try {
5411
5534
  let response = await axios(options);
5412
- let capabilities = this.capabilities();
5535
+ const capabilities = this.capabilities();
5413
5536
  if (capabilities) {
5414
5537
  response = capabilities.migrate(response);
5415
5538
  }
@@ -5433,7 +5556,7 @@ class Connection {
5433
5556
  // See: https://github.com/axios/axios/issues/815
5434
5557
  if (options.responseType === Environment.getResponseType()) {
5435
5558
  try {
5436
- let errorResponse = await Environment.handleErrorResponse(error);
5559
+ const errorResponse = await Environment.handleErrorResponse(error);
5437
5560
  throw enrichError(error, errorResponse);
5438
5561
  } catch (error2) {
5439
5562
  console.error(error2);
@@ -5909,9 +6032,26 @@ class Logs {
5909
6032
  * @type {Connection}
5910
6033
  */
5911
6034
  this.connection = connection;
6035
+ /**
6036
+ * @protected
6037
+ * @type {string}
6038
+ */
5912
6039
  this.endpoint = endpoint;
6040
+ /**
6041
+ * @protected
6042
+ * @type {string}
6043
+ */
5913
6044
  this.lastId = "";
6045
+ /**
6046
+ * @protected
6047
+ * @type {?string}
6048
+ */
5914
6049
  this.level = level;
6050
+ /**
6051
+ * @protected
6052
+ * @type {Set<string>}
6053
+ */
6054
+ this.missing = new Set();
5915
6055
  }
5916
6056
 
5917
6057
  /**
@@ -5928,6 +6068,19 @@ class Logs {
5928
6068
  return Array.isArray(response.logs) ? response.logs : [];
5929
6069
  }
5930
6070
 
6071
+ /**
6072
+ * Retrieves the backend identifiers that are (partially) missing in the logs.
6073
+ *
6074
+ * This is only filled after the first request using `nextLogs` or `next`.
6075
+ *
6076
+ * @returns {Array.<string>}
6077
+ * @see {Logs#nextLogs}
6078
+ * @see {Logs#next}
6079
+ */
6080
+ getMissingBackends() {
6081
+ return Array.from(this.missing);
6082
+ }
6083
+
5931
6084
  /**
5932
6085
  * Retrieves the next log entries since the last request.
5933
6086
  *
@@ -5955,6 +6108,9 @@ class Logs {
5955
6108
  response.data.logs = [];
5956
6109
  }
5957
6110
  response.data.links = Array.isArray(response.data.links) ? response.data.links : [];
6111
+ if (Array.isArray(response.data["federation:missing"])) {
6112
+ response.data["federation:missing"].forEach(backend => this.missing.add(backend));
6113
+ }
5958
6114
  return response.data;
5959
6115
  }
5960
6116
  }
@@ -6478,17 +6634,380 @@ module.exports = {
6478
6634
 
6479
6635
  /***/ }),
6480
6636
 
6481
- /***/ 497:
6637
+ /***/ 226:
6482
6638
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
6483
6639
 
6484
- const BaseEntity = __webpack_require__(54);
6485
- const Logs = __webpack_require__(431);
6640
+ /* eslint-disable max-classes-per-file */
6486
6641
 
6487
- /**
6488
- * A Secondary Web Service.
6489
- *
6490
- * @augments BaseEntity
6491
- */
6642
+ const Job = __webpack_require__(293);
6643
+ const Service = __webpack_require__(497);
6644
+ const UserFile = __webpack_require__(649);
6645
+ const UserProcess = __webpack_require__(806);
6646
+ const Utils = __webpack_require__(768);
6647
+ const StacMigrate = __webpack_require__(321);
6648
+ const FED_MISSING = 'federation:missing';
6649
+
6650
+ /**
6651
+ * A class to handle pagination of resources.
6652
+ *
6653
+ * @abstract
6654
+ */
6655
+ class Pages {
6656
+ /**
6657
+ * Creates an instance of Pages.
6658
+ *
6659
+ * @param {Connection} connection
6660
+ * @param {string} endpoint
6661
+ * @param {string} key
6662
+ * @param {Constructor} cls
6663
+ * @param {object} [params={}]
6664
+ * @param {string} primaryKey
6665
+ */
6666
+ constructor(connection, endpoint, key, cls, params = {}, primaryKey = "id") {
6667
+ this.connection = connection;
6668
+ this.nextUrl = endpoint;
6669
+ this.key = key;
6670
+ this.primaryKey = primaryKey;
6671
+ this.cls = cls;
6672
+ if (!(params.limit > 0)) {
6673
+ delete params.limit;
6674
+ }
6675
+ this.params = params;
6676
+ }
6677
+
6678
+ /**
6679
+ * Returns true if there are more pages to fetch.
6680
+ *
6681
+ * @returns {boolean}
6682
+ */
6683
+ hasNextPage() {
6684
+ return this.nextUrl !== null;
6685
+ }
6686
+
6687
+ /**
6688
+ * Returns the next page of resources.
6689
+ *
6690
+ * @async
6691
+ * @param {Array.<object>} oldObjects - Existing objects to update, if any.
6692
+ * @param {boolean} [toArray=true] - Whether to return the objects as a simplified array or as an object with all information.
6693
+ * @returns {Array.<object>}
6694
+ * @throws {Error}
6695
+ */
6696
+ async nextPage(oldObjects = [], toArray = true) {
6697
+ // Request data from server
6698
+ const response = await this.connection._get(this.nextUrl, this.params);
6699
+ let data = response.data;
6700
+ // Check response
6701
+ if (!Utils.isObject(data)) {
6702
+ throw new Error(`Response is invalid, is not an object`);
6703
+ }
6704
+ if (!Array.isArray(data[this.key])) {
6705
+ throw new Error(`Response is invalid, '${this.key}' property is not an array`);
6706
+ }
6707
+
6708
+ // Update existing objects if needed
6709
+ let newObjects = data[this.key].map(updated => {
6710
+ let resource = oldObjects.find(old => old[this.primaryKey] === updated[this.primaryKey]);
6711
+ if (resource) {
6712
+ resource.setAll(updated);
6713
+ } else {
6714
+ resource = this._createObject(updated);
6715
+ }
6716
+ return resource;
6717
+ });
6718
+
6719
+ // Store objects in cache if needed
6720
+ newObjects = this._cache(newObjects);
6721
+
6722
+ // Add self link if missing
6723
+ data.links = this._ensureArray(data.links);
6724
+ const selfLink = this.connection._getLinkHref(data.links, 'self');
6725
+ if (!selfLink) {
6726
+ data.links.push({
6727
+ rel: 'self',
6728
+ href: this.nextUrl
6729
+ });
6730
+ }
6731
+
6732
+ // Check whether a next page is available
6733
+ this.nextUrl = this._getNextLink(response);
6734
+ // Don't append initial params to the next URL
6735
+ this.params = null;
6736
+
6737
+ // Either return as ResponseArray or full API response body
6738
+ if (toArray) {
6739
+ newObjects.links = data.links;
6740
+ newObjects[FED_MISSING] = this._ensureArray(data[FED_MISSING]);
6741
+ return newObjects;
6742
+ } else {
6743
+ data[this.key] = newObjects;
6744
+ return data;
6745
+ }
6746
+ }
6747
+
6748
+ /**
6749
+ * Ensures a variable is an array.
6750
+ *
6751
+ * @protected
6752
+ * @param {*} x
6753
+ * @returns {Array}
6754
+ */
6755
+ _ensureArray(x) {
6756
+ return Array.isArray(x) ? x : [];
6757
+ }
6758
+
6759
+ /**
6760
+ * Creates a facade for the object, if needed.
6761
+ *
6762
+ * @protected
6763
+ * @param {object} obj
6764
+ * @returns {object}
6765
+ */
6766
+ _createObject(obj) {
6767
+ if (this.cls) {
6768
+ const cls = this.cls;
6769
+ const newObj = new cls(this.connection, obj[this.primaryKey]);
6770
+ newObj.setAll(obj);
6771
+ return newObj;
6772
+ } else {
6773
+ return obj;
6774
+ }
6775
+ }
6776
+
6777
+ /**
6778
+ * Caches the plain objects if needed.
6779
+ *
6780
+ * @param {Array.<object>} objects
6781
+ * @returns {Array.<object>}
6782
+ */
6783
+ _cache(objects) {
6784
+ return objects;
6785
+ }
6786
+
6787
+ /**
6788
+ * Get the URL of the next page from a response.
6789
+ *
6790
+ * @protected
6791
+ * @param {AxiosResponse} response
6792
+ * @returns {string | null}
6793
+ */
6794
+ _getNextLink(response) {
6795
+ const links = this.connection.makeLinksAbsolute(response.data.links, response);
6796
+ return this.connection._getLinkHref(links, 'next');
6797
+ }
6798
+
6799
+ /**
6800
+ * Makes this class asynchronously iterable.
6801
+ *
6802
+ * @returns {AsyncIterator}
6803
+ */
6804
+ [Symbol.asyncIterator]() {
6805
+ return {
6806
+ self: this,
6807
+ /**
6808
+ * Get the next page of resources.
6809
+ *
6810
+ * @async
6811
+ * @returns {{done: boolean, value: Array.<object>}}
6812
+ */
6813
+ async next() {
6814
+ const done = !this.self.hasNextPage();
6815
+ let value;
6816
+ if (!done) {
6817
+ value = await this.self.nextPage();
6818
+ }
6819
+ return {
6820
+ done,
6821
+ value
6822
+ };
6823
+ }
6824
+ };
6825
+ }
6826
+ }
6827
+
6828
+ /**
6829
+ * Paginate through jobs.
6830
+ */
6831
+ class JobPages extends Pages {
6832
+ /**
6833
+ * Paginate through jobs.
6834
+ *
6835
+ * @param {Connection} connection
6836
+ * @param {?number} limit
6837
+ */
6838
+ constructor(connection, limit = null) {
6839
+ super(connection, "/jobs", "jobs", Job, {
6840
+ limit
6841
+ });
6842
+ }
6843
+ }
6844
+
6845
+ /**
6846
+ * Paginate through services.
6847
+ */
6848
+ class ServicePages extends Pages {
6849
+ /**
6850
+ * Paginate through services.
6851
+ *
6852
+ * @param {Connection} connection
6853
+ * @param {?number} limit
6854
+ */
6855
+ constructor(connection, limit = null) {
6856
+ super(connection, "/services", "services", Service, {
6857
+ limit
6858
+ });
6859
+ }
6860
+ }
6861
+
6862
+ /**
6863
+ * Paginate through user files.
6864
+ */
6865
+ class UserFilePages extends Pages {
6866
+ /**
6867
+ * Paginate through user files.
6868
+ *
6869
+ * @param {Connection} connection
6870
+ * @param {?number} limit
6871
+ */
6872
+ constructor(connection, limit = null) {
6873
+ super(connection, "/files", "files", UserFile, {
6874
+ limit
6875
+ }, "path");
6876
+ }
6877
+ }
6878
+
6879
+ /**
6880
+ * Paginate through processes.
6881
+ */
6882
+ class ProcessPages extends Pages {
6883
+ /**
6884
+ * Paginate through processes.
6885
+ *
6886
+ * @param {Connection} connection
6887
+ * @param {?number} limit
6888
+ * @param {?string} namespace
6889
+ */
6890
+ constructor(connection, limit = null, namespace = null) {
6891
+ if (!namespace) {
6892
+ namespace = 'backend';
6893
+ }
6894
+ let endpoint;
6895
+ let cls = null;
6896
+ if (namespace === 'user') {
6897
+ endpoint = '/process_graphs';
6898
+ cls = UserProcess;
6899
+ } else {
6900
+ endpoint = '/processes';
6901
+ if (namespace !== 'backend') {
6902
+ const normalized = connection.normalizeNamespace(namespace);
6903
+ endpoint += `/${normalized}`;
6904
+ }
6905
+ }
6906
+ super(connection, endpoint, "processes", cls, {
6907
+ limit
6908
+ });
6909
+ this.namespace = namespace;
6910
+ }
6911
+
6912
+ /**
6913
+ * Caches the objects to the ProcessRegistry.
6914
+ *
6915
+ * @param {Array.<object>} objects
6916
+ * @returns {Array.<object>}
6917
+ */
6918
+ _cache(objects) {
6919
+ const plainObjects = objects.map(p => typeof p.toJSON === 'function' ? p.toJSON() : p);
6920
+ this.connection.processes.addAll(plainObjects, this.namespace);
6921
+ if (!this.cls) {
6922
+ for (let i in objects) {
6923
+ objects[i] = this.connection.processes.get(objects[i].id, this.namespace);
6924
+ }
6925
+ }
6926
+ return objects;
6927
+ }
6928
+ }
6929
+
6930
+ /**
6931
+ * Paginate through collections.
6932
+ */
6933
+ class CollectionPages extends Pages {
6934
+ /**
6935
+ * Paginate through collections.
6936
+ *
6937
+ * @param {Connection} connection
6938
+ * @param {?number} limit
6939
+ */
6940
+ constructor(connection, limit = null) {
6941
+ super(connection, "/collections", "collections", null, {
6942
+ limit
6943
+ });
6944
+ }
6945
+
6946
+ /**
6947
+ * Migrates the STAC collection to the latest version.
6948
+ *
6949
+ * @param {object} obj
6950
+ * @returns {Collection}
6951
+ */
6952
+ _createObject(obj) {
6953
+ if (obj.stac_version) {
6954
+ return StacMigrate.collection(obj);
6955
+ }
6956
+ return obj;
6957
+ }
6958
+ }
6959
+
6960
+ /**
6961
+ * Paginate through collection items.
6962
+ */
6963
+ class ItemPages extends Pages {
6964
+ /**
6965
+ * Paginate through collection items.
6966
+ *
6967
+ * @param {Connection} connection
6968
+ * @param {string} collectionId
6969
+ * @param {object} params
6970
+ */
6971
+ constructor(connection, collectionId, params) {
6972
+ super(connection, `/collections/${collectionId}/items`, "features", null, params);
6973
+ }
6974
+
6975
+ /**
6976
+ * Migrates the STAC item to the latest version.
6977
+ *
6978
+ * @param {object} obj
6979
+ * @returns {Item}
6980
+ */
6981
+ _createObject(obj) {
6982
+ if (obj.stac_version) {
6983
+ return StacMigrate.item(obj);
6984
+ }
6985
+ return obj;
6986
+ }
6987
+ }
6988
+ module.exports = {
6989
+ Pages,
6990
+ CollectionPages,
6991
+ ItemPages,
6992
+ JobPages,
6993
+ ProcessPages,
6994
+ ServicePages,
6995
+ UserFilePages
6996
+ };
6997
+
6998
+ /***/ }),
6999
+
7000
+ /***/ 497:
7001
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
7002
+
7003
+ const BaseEntity = __webpack_require__(54);
7004
+ const Logs = __webpack_require__(431);
7005
+
7006
+ /**
7007
+ * A Secondary Web Service.
7008
+ *
7009
+ * @augments BaseEntity
7010
+ */
6492
7011
  class Service extends BaseEntity {
6493
7012
  /**
6494
7013
  * Creates an object representing a secondary web service stored at the back-end.
@@ -6989,124 +7508,240 @@ module.exports = UserProcess;
6989
7508
 
6990
7509
  /***/ }),
6991
7510
 
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
- }
7511
+ /***/ 385:
7512
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
7011
7513
 
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
- }
7023
-
7024
- function validate(version) {
7514
+ "use strict";
7515
+ // ESM COMPAT FLAG
7516
+ __webpack_require__.r(__webpack_exports__);
7517
+
7518
+ // EXPORTS
7519
+ __webpack_require__.d(__webpack_exports__, {
7520
+ compare: () => (/* reexport */ compare),
7521
+ compareVersions: () => (/* reexport */ compareVersions),
7522
+ satisfies: () => (/* reexport */ satisfies),
7523
+ validate: () => (/* reexport */ validate),
7524
+ validateStrict: () => (/* reexport */ validateStrict)
7525
+ });
7526
+
7527
+ ;// ./node_modules/compare-versions/lib/esm/utils.js
7528
+ const semver = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
7529
+ const validateAndParse = (version) => {
7025
7530
  if (typeof version !== 'string') {
7026
- throw new TypeError('Invalid argument expected string');
7531
+ throw new TypeError('Invalid argument expected string');
7027
7532
  }
7028
- if (!semver.test(version)) {
7029
- throw new Error('Invalid argument not valid semver (\''+version+'\' received)');
7533
+ const match = version.match(semver);
7534
+ if (!match) {
7535
+ throw new Error(`Invalid argument not valid semver ('${version}' received)`);
7030
7536
  }
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;
7537
+ match.shift();
7538
+ return match;
7539
+ };
7540
+ const isWildcard = (s) => s === '*' || s === 'x' || s === 'X';
7541
+ const tryParse = (v) => {
7542
+ const n = parseInt(v, 10);
7543
+ return isNaN(n) ? v : n;
7544
+ };
7545
+ const forceType = (a, b) => typeof a !== typeof b ? [String(a), String(b)] : [a, b];
7546
+ const compareStrings = (a, b) => {
7547
+ if (isWildcard(a) || isWildcard(b))
7548
+ return 0;
7549
+ const [ap, bp] = forceType(tryParse(a), tryParse(b));
7550
+ if (ap > bp)
7551
+ return 1;
7552
+ if (ap < bp)
7553
+ return -1;
7554
+ return 0;
7555
+ };
7556
+ const compareSegments = (a, b) => {
7557
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
7558
+ const r = compareStrings(a[i] || '0', b[i] || '0');
7559
+ if (r !== 0)
7560
+ return r;
7045
7561
  }
7562
+ return 0;
7563
+ };
7564
+ //# sourceMappingURL=utils.js.map
7565
+ ;// ./node_modules/compare-versions/lib/esm/compareVersions.js
7046
7566
 
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;
7567
+ /**
7568
+ * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.
7569
+ * 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`.
7570
+ * @param v1 - First version to compare
7571
+ * @param v2 - Second version to compare
7572
+ * @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).
7573
+ */
7574
+ const compareVersions = (v1, v2) => {
7575
+ // validate input and split into segments
7576
+ const n1 = validateAndParse(v1);
7577
+ const n2 = validateAndParse(v2);
7578
+ // pop off the patch
7579
+ const p1 = n1.pop();
7580
+ const p2 = n2.pop();
7581
+ // validate numbers
7582
+ const r = compareSegments(n1, n2);
7583
+ if (r !== 0)
7584
+ return r;
7585
+ // validate pre-release
7586
+ if (p1 && p2) {
7587
+ return compareSegments(p1.split('.'), p2.split('.'));
7588
+ }
7589
+ else if (p1 || p2) {
7590
+ return p1 ? -1 : 1;
7063
7591
  }
7064
-
7065
7592
  return 0;
7066
- };
7067
-
7068
- var allowedOperators = [
7069
- '>',
7070
- '>=',
7071
- '=',
7072
- '<',
7073
- '<='
7074
- ];
7593
+ };
7594
+ //# sourceMappingURL=compareVersions.js.map
7595
+ ;// ./node_modules/compare-versions/lib/esm/compare.js
7075
7596
 
7076
- var operatorResMap = {
7597
+ /**
7598
+ * Compare [semver](https://semver.org/) version strings using the specified operator.
7599
+ *
7600
+ * @param v1 First version to compare
7601
+ * @param v2 Second version to compare
7602
+ * @param operator Allowed arithmetic operator to use
7603
+ * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise.
7604
+ *
7605
+ * @example
7606
+ * ```
7607
+ * compare('10.1.8', '10.0.4', '>'); // return true
7608
+ * compare('10.0.1', '10.0.1', '='); // return true
7609
+ * compare('10.1.1', '10.2.2', '<'); // return true
7610
+ * compare('10.1.1', '10.2.2', '<='); // return true
7611
+ * compare('10.1.1', '10.2.2', '>='); // return false
7612
+ * ```
7613
+ */
7614
+ const compare = (v1, v2, operator) => {
7615
+ // validate input operator
7616
+ assertValidOperator(operator);
7617
+ // since result of compareVersions can only be -1 or 0 or 1
7618
+ // a simple map can be used to replace switch
7619
+ const res = compareVersions(v1, v2);
7620
+ return operatorResMap[operator].includes(res);
7621
+ };
7622
+ const operatorResMap = {
7077
7623
  '>': [1],
7078
7624
  '>=': [0, 1],
7079
7625
  '=': [0],
7080
7626
  '<=': [-1, 0],
7081
- '<': [-1]
7082
- };
7083
-
7084
- function validateOperator(op) {
7627
+ '<': [-1],
7628
+ '!=': [-1, 1],
7629
+ };
7630
+ const allowedOperators = Object.keys(operatorResMap);
7631
+ const assertValidOperator = (op) => {
7085
7632
  if (typeof op !== 'string') {
7086
- throw new TypeError('Invalid operator type, expected string but got ' + typeof op);
7633
+ throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`);
7087
7634
  }
7088
7635
  if (allowedOperators.indexOf(op) === -1) {
7089
- throw new TypeError('Invalid operator, expected one of ' + allowedOperators.join('|'));
7636
+ throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`);
7090
7637
  }
7091
- }
7638
+ };
7639
+ //# sourceMappingURL=compare.js.map
7640
+ ;// ./node_modules/compare-versions/lib/esm/satisfies.js
7092
7641
 
7093
- compareVersions.validate = function(version) {
7094
- return typeof version === 'string' && semver.test(version);
7095
- }
7096
7642
 
7097
- compareVersions.compare = function (v1, v2, operator) {
7098
- // Validate operator
7099
- validateOperator(operator);
7643
+ /**
7644
+ * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range.
7645
+ *
7646
+ * @param version Version number to match
7647
+ * @param range Range pattern for version
7648
+ * @returns `true` if the version number is within the range, `false` otherwise.
7649
+ *
7650
+ * @example
7651
+ * ```
7652
+ * satisfies('1.1.0', '^1.0.0'); // return true
7653
+ * satisfies('1.1.0', '~1.0.0'); // return false
7654
+ * ```
7655
+ */
7656
+ const satisfies = (version, range) => {
7657
+ // clean input
7658
+ range = range.replace(/([><=]+)\s+/g, '$1');
7659
+ // handle multiple comparators
7660
+ if (range.includes('||')) {
7661
+ return range.split('||').some((r) => satisfies(version, r));
7662
+ }
7663
+ else if (range.includes(' - ')) {
7664
+ const [a, b] = range.split(' - ', 2);
7665
+ return satisfies(version, `>=${a} <=${b}`);
7666
+ }
7667
+ else if (range.includes(' ')) {
7668
+ return range
7669
+ .trim()
7670
+ .replace(/\s{2,}/g, ' ')
7671
+ .split(' ')
7672
+ .every((r) => satisfies(version, r));
7673
+ }
7674
+ // if no range operator then "="
7675
+ const m = range.match(/^([<>=~^]+)/);
7676
+ const op = m ? m[1] : '=';
7677
+ // if gt/lt/eq then operator compare
7678
+ if (op !== '^' && op !== '~')
7679
+ return compare(version, range, op);
7680
+ // else range of either "~" or "^" is assumed
7681
+ const [v1, v2, v3, , vp] = validateAndParse(version);
7682
+ const [r1, r2, r3, , rp] = validateAndParse(range);
7683
+ const v = [v1, v2, v3];
7684
+ const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x'];
7685
+ // validate pre-release
7686
+ if (rp) {
7687
+ if (!vp)
7688
+ return false;
7689
+ if (compareSegments(v, r) !== 0)
7690
+ return false;
7691
+ if (compareSegments(vp.split('.'), rp.split('.')) === -1)
7692
+ return false;
7693
+ }
7694
+ // first non-zero number
7695
+ const nonZero = r.findIndex((v) => v !== '0') + 1;
7696
+ // pointer to where segments can be >=
7697
+ const i = op === '~' ? 2 : nonZero > 1 ? nonZero : 1;
7698
+ // before pointer must be equal
7699
+ if (compareSegments(v.slice(0, i), r.slice(0, i)) !== 0)
7700
+ return false;
7701
+ // after pointer must be >=
7702
+ if (compareSegments(v.slice(i), r.slice(i)) === -1)
7703
+ return false;
7704
+ return true;
7705
+ };
7706
+ //# sourceMappingURL=satisfies.js.map
7707
+ ;// ./node_modules/compare-versions/lib/esm/validate.js
7708
+
7709
+ /**
7710
+ * Validate [semver](https://semver.org/) version strings.
7711
+ *
7712
+ * @param version Version number to validate
7713
+ * @returns `true` if the version number is a valid semver version number, `false` otherwise.
7714
+ *
7715
+ * @example
7716
+ * ```
7717
+ * validate('1.0.0-rc.1'); // return true
7718
+ * validate('1.0-rc.1'); // return false
7719
+ * validate('foo'); // return false
7720
+ * ```
7721
+ */
7722
+ const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version);
7723
+ /**
7724
+ * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges.
7725
+ *
7726
+ * @param version Version number to validate
7727
+ * @returns `true` if the version number is a valid semver version number `false` otherwise
7728
+ *
7729
+ * @example
7730
+ * ```
7731
+ * validate('1.0.0-rc.1'); // return true
7732
+ * validate('1.0-rc.1'); // return false
7733
+ * validate('foo'); // return false
7734
+ * ```
7735
+ */
7736
+ const validateStrict = (version) => typeof version === 'string' &&
7737
+ /^(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);
7738
+ //# sourceMappingURL=validate.js.map
7739
+ ;// ./node_modules/compare-versions/lib/esm/index.js
7740
+
7100
7741
 
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
7742
 
7107
- return compareVersions;
7108
- }));
7109
7743
 
7744
+ //# sourceMappingURL=index.js.map
7110
7745
 
7111
7746
  /***/ }),
7112
7747
 
@@ -7233,6 +7868,35 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__742__;
7233
7868
  /******/ }
7234
7869
  /******/
7235
7870
  /************************************************************************/
7871
+ /******/ /* webpack/runtime/define property getters */
7872
+ /******/ (() => {
7873
+ /******/ // define getter functions for harmony exports
7874
+ /******/ __webpack_require__.d = (exports, definition) => {
7875
+ /******/ for(var key in definition) {
7876
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
7877
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
7878
+ /******/ }
7879
+ /******/ }
7880
+ /******/ };
7881
+ /******/ })();
7882
+ /******/
7883
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
7884
+ /******/ (() => {
7885
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
7886
+ /******/ })();
7887
+ /******/
7888
+ /******/ /* webpack/runtime/make namespace object */
7889
+ /******/ (() => {
7890
+ /******/ // define __esModule on exports
7891
+ /******/ __webpack_require__.r = (exports) => {
7892
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
7893
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7894
+ /******/ }
7895
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
7896
+ /******/ };
7897
+ /******/ })();
7898
+ /******/
7899
+ /************************************************************************/
7236
7900
  /******/
7237
7901
  /******/ // startup
7238
7902
  /******/ // Load entry module and return exports