@openeo/js-commons
Advanced tools
Comparing version 1.0.0-rc.4 to 1.0.0
571
dist/main.js
@@ -94,3 +94,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 2); | ||
/******/ return __webpack_require__(__webpack_require__.s = 3); | ||
/******/ }) | ||
@@ -102,2 +102,3 @@ /************************************************************************/ | ||
/** General utilities */ | ||
class Utils { | ||
@@ -118,2 +119,10 @@ | ||
/** | ||
* Computes the size of an array (number of array elements) or object (number of key-value-pairs). | ||
* | ||
* Returns 0 for all other data types. | ||
* | ||
* @param {*} obj | ||
* @returns {integer} | ||
*/ | ||
static size(obj) { | ||
@@ -146,4 +155,4 @@ if (typeof obj === 'object' && obj !== null) { | ||
* | ||
* @param {*} x | ||
* @returns {*} | ||
* @param {*} x - The data to clone. | ||
* @returns {*} - The cloned data. | ||
*/ | ||
@@ -155,3 +164,3 @@ static deepClone(x) { | ||
/** | ||
* Normalize a URL (mostly handling slashes). | ||
* Normalize a URL (mostly handling leading and trailing slashes). | ||
* | ||
@@ -174,2 +183,10 @@ * @static | ||
/** | ||
* Replaces placeholders in this format: `{var}`. | ||
* | ||
* This can be used for the placeholders/variables in the openEO API's errors.json file. | ||
* | ||
* @param {string} message - The string to replace the placeholders in. | ||
* @param {object} variables - A map with the placeholder names as keys and the replacement value as value. | ||
*/ | ||
static replacePlaceholders(message, variables = {}) { | ||
@@ -185,2 +202,101 @@ if (typeof message === 'string' && Utils.isObject(variables)) { | ||
/** | ||
* Compares two strings case-insensitive, including natural ordering for numbers. | ||
* | ||
* @param {string} a | ||
* @param {string} b | ||
* @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). | ||
*/ | ||
static compareStringCaseInsensitive(a, b) { | ||
if (typeof a !== 'string') { | ||
a = String(a); | ||
} | ||
if (typeof b !== 'string') { | ||
b = String(b); | ||
} | ||
return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'}); | ||
} | ||
/** | ||
* Tries to make a string more readable by capitalizing it. | ||
* Only applies to words with more than two characters. | ||
* | ||
* Supports converting from: | ||
* - Snake Case (abc_def => Abc Def) | ||
* - Kebab Case (abc-def => Abc Def) | ||
* - Camel Case (abcDef => Abc Def) | ||
* | ||
* Doesn't capitalize if the words are not in any of the casing formats above. | ||
* | ||
* @param {*} strings - String(s) to make readable | ||
* @param {string} arraySep - String to separate array elements with | ||
* @returns {string} | ||
*/ | ||
static prettifyString(strings, arraySep = '; ') { | ||
if (!Array.isArray(strings)) { | ||
strings = [String(strings)]; | ||
} | ||
strings = strings.map(str => { | ||
if (str.length >= 3) { | ||
const replacer = (_,a,b) => a + ' ' + b.toUpperCase(); | ||
if (str.includes('_')) { | ||
// Snake case converter | ||
str = str.replace(/([a-zA-Z\d])_([a-zA-Z\d])/g, replacer); | ||
} | ||
else if (str.includes('-')) { | ||
// Kebab case converter | ||
str = str.replace(/([a-zA-Z\d])-([a-zA-Z\d])/g, replacer); | ||
} | ||
else { | ||
// Camelcase converter | ||
str = str.replace(/([a-z])([A-Z])/g, replacer); | ||
} | ||
// Uppercase the first letter in the first word, too. | ||
return str.charAt(0).toUpperCase() + str.substr(1); | ||
} | ||
return str; | ||
}); | ||
return strings.join(arraySep); | ||
} | ||
/** | ||
* Makes link lists from the openEO API more user-friendly. | ||
* | ||
* Supports: | ||
* - Set a reasonable title, if not available. Make title more readable. | ||
* - Sorting by title (see `sort` parameter) | ||
* - Removing given relation types (`rel` property, see `ignoreRel` parameter) | ||
* | ||
* @param {array} linkList - List of links | ||
* @param {boolean} sort - Enable/Disable sorting by title. Enabled (true) by default. | ||
* @param {array} ignoreRel - A list of rel types to remove. By default, removes the self links (rel type = `self`). | ||
* @returns {array} | ||
*/ | ||
static friendlyLinks(linkList, sort = true, ignoreRel = ['self']) { | ||
let links = []; | ||
if (!Array.isArray(linkList)) { | ||
return links; | ||
} | ||
for(let link of linkList) { | ||
link = Object.assign({}, link); // Make sure to work on a copy | ||
if (typeof link.rel === 'string' && ignoreRel.includes(link.rel.toLowerCase())) { | ||
continue; | ||
} | ||
if (typeof link.title !== 'string' || link.title.length === 0) { | ||
if (typeof link.rel === 'string' && link.rel.length > 1) { | ||
link.title = Utils.prettifyString(link.rel); | ||
} | ||
else { | ||
link.title = link.href.replace(/^https?:\/\/(www.)?/i, '').replace(/\/$/i, ''); | ||
} | ||
} | ||
links.push(link); | ||
} | ||
if (sort) { | ||
links.sort((a, b) => Utils.compareStringCaseInsensitive(a.title, b.title)); | ||
} | ||
return links; | ||
} | ||
} | ||
@@ -194,6 +310,16 @@ | ||
const VersionCompare = __webpack_require__(4); | ||
const VersionCompare = __webpack_require__(5); | ||
/** Version Number related methods */ | ||
class Versions { | ||
/** | ||
* Compare [semver](https://semver.org/) version strings. | ||
* | ||
* @param {string} firstVersion First version to compare | ||
* @param {string} secondVersion Second version to compare | ||
* @param {string|null} operator Optional; Arithmetic operator to use (>, >=, =, <=, <, !=). Defaults to `null`. | ||
* @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). | ||
* ``` | ||
*/ | ||
static compare(v1, v2, operator = null) { | ||
@@ -208,2 +334,8 @@ if (operator !== null) { | ||
/** | ||
* Validate [semver](https://semver.org/) version strings. | ||
* | ||
* @param {*} version - Version number to validate | ||
* @returns - `true` if the version number is a valid semver version number, `false` otherwise. | ||
*/ | ||
static validate(version) { | ||
@@ -218,2 +350,5 @@ return VersionCompare.validate(version); | ||
* @param {array} wkVersions - A well-known discovery document compliant to the API specification. | ||
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions. | ||
* @param {string|null} minVersion - The minimum version that should be returned. | ||
* @param {string|null} maxVersion - The maximum version that should be returned. | ||
* @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable. | ||
@@ -264,2 +399,13 @@ */ | ||
/** | ||
* Find the latest version from well-known discovery that applies to the specified rules. | ||
* | ||
* This is basically the same as calling `findCompatible` and using the first element from the result. | ||
* | ||
* @param {array} wkVersions - A well-known discovery document compliant to the API specification. | ||
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions. | ||
* @param {string|null} minVersion - The minimum version that should be returned. | ||
* @param {string|null} maxVersion - The maximum version that should be returned. | ||
* @returns {object|null} | ||
*/ | ||
static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) { | ||
@@ -283,6 +429,58 @@ let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion); | ||
const Utils = __webpack_require__(0); | ||
const Versions = __webpack_require__(1); | ||
class MigrateCommons { | ||
static migrateLinks(links, version, fallbackRel = 'related') { | ||
if (!Array.isArray(links)) { | ||
return []; | ||
} | ||
return links | ||
.filter(link => Utils.isObject(link) && typeof link.href === 'string') | ||
.map(link => { | ||
if (typeof link.rel !== 'string') { | ||
link.rel = fallbackRel; | ||
} | ||
return link; | ||
}); | ||
} | ||
static migrateDiscoveryParameters(parameters, version) { | ||
if (Versions.compare(version, "1.0.0-rc.2", "<=")) { | ||
for(var name in parameters) { | ||
if (!Utils.isObject(parameters[name])) { | ||
delete parameters[name]; | ||
continue; | ||
} | ||
let type = parameters[name].type; | ||
if (typeof type === 'string') { | ||
parameters[name].type = [type, "null"]; | ||
} | ||
let example = parameters[name].example; | ||
if (typeof example !== 'undefined') { | ||
parameters[name].examples = [example]; | ||
delete parameters[name].example; | ||
} | ||
} | ||
} | ||
return parameters; | ||
} | ||
} | ||
module.exports = MigrateCommons; | ||
/***/ }), | ||
/* 3 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
// Migrations | ||
const MigrateCapabilities = __webpack_require__(3); | ||
const MigrateCollections = __webpack_require__(5); | ||
const MigrateProcesses = __webpack_require__(6); | ||
const MigrateCapabilities = __webpack_require__(4); | ||
const MigrateCollections = __webpack_require__(6); | ||
const MigrateProcesses = __webpack_require__(7); | ||
// Others | ||
@@ -301,3 +499,3 @@ const Versions = __webpack_require__(1); | ||
/***/ }), | ||
/* 3 */ | ||
/* 4 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -307,5 +505,7 @@ | ||
const Versions = __webpack_require__(1); | ||
const MigrateCommons = __webpack_require__(2); | ||
const NO_VERSION = "0.0.0"; | ||
/** Migrate capabilities related responses to the latest version. */ | ||
class MigrateCapabilities { | ||
@@ -351,4 +551,17 @@ | ||
// Always returns a copy of the input object | ||
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "Unknown") { | ||
/** | ||
* Converts a `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string|null} version - Version number of the API, which the response conforms to. If `null`, tries to guess the version with `guessApiVersion()`. | ||
* @param {boolean} updateVersionNumbers - Should version numbers in the response be updated? | ||
* @param {boolean} updateEndpointPaths - Should the endpoint paths be updated to their recent equivalents? | ||
* @param {string} id - If no id is set in the response, sets it to the value specified here. Defaults to `unknown`. | ||
* @param {string} title - If no title is set in the response, sets it to the value specified here. Defaults to `Unknown`. | ||
* @param {string} title - If no backend_version is set in the response, sets it to the value specified here. Defaults to `0.0.0`. | ||
* @returns {object} | ||
*/ | ||
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "0.0.0") { | ||
if (version === null) { | ||
@@ -410,5 +623,3 @@ version = this.guessApiVersion(originalCapabilities); | ||
} | ||
if (!Array.isArray(capabilities.links)) { | ||
capabilities.links = []; | ||
} | ||
capabilities.links = MigrateCommons.migrateLinks(capabilities.links, version); | ||
@@ -418,11 +629,21 @@ return capabilities; | ||
// Always returns a copy of the input object | ||
static convertBillingToLatestSpec(originalBilling, version) { | ||
/** | ||
* Converts the billing part of the `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} billing - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertBillingToLatestSpec(billing, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let billing = {}; | ||
if (Utils.isObject(originalBilling)) { | ||
billing = Utils.deepClone(originalBilling); | ||
if (Utils.isObject(billing)) { | ||
billing = Utils.deepClone(billing); | ||
} | ||
else { | ||
billing = {}; | ||
} | ||
@@ -436,11 +657,20 @@ if (typeof billing.currency !== 'string') { | ||
// Always returns a copy of the input object | ||
static convertEndpointsToLatestSpec(originalEndpoints, version, updatePaths = false) { | ||
/** | ||
* Converts the endpoints part of the `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {array} endpoints - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @param {boolean} updatePaths - Should the endpoint paths be updated to their recent equivalents? | ||
* @returns {array} | ||
*/ | ||
static convertEndpointsToLatestSpec(endpoints, version, updatePaths = false) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
if (!Array.isArray(originalEndpoints)) { | ||
if (!Array.isArray(endpoints)) { | ||
return []; | ||
} | ||
let endpoints = Utils.deepClone(originalEndpoints); | ||
endpoints = Utils.deepClone(endpoints); | ||
// convert v0.4 endpoints to v1.0 | ||
@@ -506,16 +736,34 @@ if (updatePaths) { | ||
// Alias for convertFileFormatsToLatestSpec | ||
static convertOutputFormatsToLatestSpec(originalFormats, version) { | ||
return this.convertFileFormatsToLatestSpec(originalFormats, version); | ||
/** | ||
* Alias for `convertFileFormatsToLatestSpec()`. | ||
* | ||
* @alias MigrateCapabilities.convertFileFormatsToLatestSpec | ||
* @deprecated | ||
* @param {object} formats - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertOutputFormatsToLatestSpec(formats, version) { | ||
return this.convertFileFormatsToLatestSpec(formats, version); | ||
} | ||
// Always returns a copy of the input object | ||
static convertFileFormatsToLatestSpec(originalFormats, version) { | ||
/** | ||
* Converts a `GET /file_formats` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} formats - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertFileFormatsToLatestSpec(formats, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let formats = {}; | ||
if (Utils.isObject(originalFormats)) { | ||
formats = Utils.deepClone(originalFormats); | ||
if (Utils.isObject(formats)) { | ||
formats = Utils.deepClone(formats); | ||
} | ||
else { | ||
formats = {}; | ||
} | ||
@@ -528,8 +776,4 @@ if (Versions.compare(version, "0.4.x", "=") && Utils.isObject(formats)) { | ||
if (!Utils.isObject(formats.input)) { | ||
formats.input = {}; | ||
} | ||
if (!Utils.isObject(formats.output)) { | ||
formats.output = {}; | ||
} | ||
formats.input = upgradeFileFormats(formats.input, version); | ||
formats.output = upgradeFileFormats(formats.output, version); | ||
@@ -539,18 +783,25 @@ return formats; | ||
// Always returns a copy of the input object | ||
static convertServiceTypesToLatestSpec(originalTypes, version) { | ||
/** | ||
* Converts a `GET /service_types` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} types - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertServiceTypesToLatestSpec(types, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let types = {}; | ||
if (Utils.isObject(originalTypes)) { | ||
types = Utils.deepClone(originalTypes); | ||
if (!Utils.isObject(types)) { | ||
return {}; | ||
} | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
for(let t in types) { | ||
if (!Utils.isObject(types[t])) { | ||
types[t] = {}; | ||
continue; | ||
} | ||
types = Utils.deepClone(types); | ||
for(let t in types) { | ||
if (!Utils.isObject(types[t])) { | ||
types[t] = {}; | ||
} | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
// Remove attributes | ||
@@ -560,3 +811,2 @@ delete types[t].attributes; | ||
// Rename parameters to configuration | ||
if (Utils.isObject(types[t].parameters)) { | ||
@@ -588,2 +838,17 @@ types[t].configuration = types[t].parameters; | ||
} | ||
if (!Utils.isObject(types[t].configuration)) { | ||
types[t].configuration = {}; | ||
} | ||
else { | ||
types[t].configuration = MigrateCommons.migrateDiscoveryParameters(types[t].configuration, version); | ||
} | ||
if (!Array.isArray(types[t].process_parameters)) { | ||
types[t].process_parameters = []; | ||
} | ||
if (typeof types[t].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
types[t].links = MigrateCommons.migrateLinks(types[t].links, version); | ||
} | ||
} | ||
@@ -593,11 +858,23 @@ return types; | ||
// Always returns a copy of the input object | ||
static convertUdfRuntimesToLatestSpec(originalRuntimes, version) { | ||
/** | ||
* Converts a `GET /udf_runtimes` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} runtimes - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertUdfRuntimesToLatestSpec(runtimes, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let runtimes = Utils.deepClone(originalRuntimes); | ||
if (!Utils.isObject(runtimes)) { | ||
return {}; | ||
} | ||
runtimes = Utils.deepClone(runtimes); | ||
for(let r in runtimes) { | ||
// Nothing to do, was not supported in 0.3 and nothing changed in 0.4. | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
for(let r in runtimes) { | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
if (!Utils.isObject(runtimes[r])) { | ||
@@ -613,3 +890,17 @@ delete runtimes[r]; | ||
} | ||
if (typeof runtimes[r].type !== 'string') { | ||
if (typeof runtimes[r].docker === 'string') { | ||
runtimes[r].type = 'docker'; | ||
} | ||
else { | ||
runtimes[r].type = 'language'; | ||
} | ||
} | ||
if (typeof runtimes[r].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
runtimes[r].links = MigrateCommons.migrateLinks(runtimes[r].links, version); | ||
} | ||
} | ||
return runtimes; | ||
@@ -620,6 +911,35 @@ } | ||
const GIS_DATA_TYPES = ['raster', 'vector', 'table', 'other']; | ||
function upgradeFileFormats(formats, version) { | ||
if (!Utils.isObject(formats)) { | ||
formats = {}; | ||
} | ||
for(let id in formats) { | ||
if (!Utils.isObject(formats[id].parameters)) { | ||
formats[id].parameters = {}; | ||
} | ||
else { | ||
formats[id].parameters = MigrateCommons.migrateDiscoveryParameters(formats[id].parameters, version); | ||
} | ||
// Can be empty: https://github.com/Open-EO/openeo-api/issues/325 | ||
if (!Array.isArray(formats[id].gis_data_types)) { | ||
formats[id].gis_data_types = []; | ||
} | ||
else { | ||
formats[id].gis_data_types = formats[id].gis_data_types.filter(t => GIS_DATA_TYPES.includes(t)); | ||
} | ||
if (typeof formats[id].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
formats[id].links = MigrateCommons.migrateLinks(formats[id].links, version); | ||
} | ||
} | ||
return formats; | ||
} | ||
module.exports = MigrateCapabilities; | ||
/***/ }), | ||
/* 4 */ | ||
/* 5 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -744,3 +1064,3 @@ | ||
/***/ }), | ||
/* 5 */ | ||
/* 6 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -750,2 +1070,3 @@ | ||
const Versions = __webpack_require__(1); | ||
const MigrateCommons = __webpack_require__(2); | ||
@@ -808,5 +1129,53 @@ const extMap = { | ||
const DIMENSION_TYPES = [ | ||
'spatial', | ||
'temporal', | ||
'bands', | ||
'other' | ||
]; | ||
/** Migrate Collections related responses to the latest version. */ | ||
class MigrateCollections { | ||
// Always returns a copy of the input collection object | ||
/** | ||
* Converts a `GET /collections` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertCollectionsToLatestSpec(response, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
// Make sure we don't alter the original object | ||
response = Utils.deepClone(response); | ||
if (Array.isArray(response.collections)) { | ||
response.collections = response.collections | ||
.map(c => MigrateCollections.convertCollectionToLatestSpec(c, version)) | ||
.filter(c => typeof c.id === 'string'); | ||
} | ||
else { | ||
response.collections = []; | ||
} | ||
response.links = MigrateCommons.migrateLinks(response.links, version); | ||
return response; | ||
} | ||
/** | ||
* Converts a single collection to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} process - The collection to convert | ||
* @param {string} version - Version number of the API, which the collection conforms to | ||
* @returns {object} | ||
*/ | ||
static convertCollectionToLatestSpec(originalCollection, version) { | ||
@@ -905,3 +1274,5 @@ if (Versions.compare(version, "0.3.x", "<=")) { | ||
collection.summaries = Utils.isObject(collection.summaries) ? collection.summaries : {}; | ||
if (!Utils.isObject(collection.summaries)) { | ||
collection.summaries = {}; | ||
} | ||
for(let key in props) { | ||
@@ -957,12 +1328,12 @@ let val = props[key]; | ||
} | ||
else { | ||
for(var name in collection['cube:dimensions']) { | ||
if (Utils.isObject(collection['cube:dimensions'][name]) && !DIMENSION_TYPES.includes(collection['cube:dimensions'][name].type)) { | ||
collection['cube:dimensions'][name].type = 'other'; | ||
} | ||
} | ||
} | ||
// Fix links | ||
if (!Array.isArray(collection.links)) { | ||
collection.links = []; | ||
} | ||
// Add missing rel type | ||
collection.links = collection.links.map(l => { | ||
l.rel = typeof l.rel === 'string' ? l.rel : "related"; | ||
return l; | ||
}); | ||
collection.links = MigrateCommons.migrateLinks(collection.links); | ||
@@ -996,3 +1367,3 @@ // Fix stac_extensions | ||
/***/ }), | ||
/* 6 */ | ||
/* 7 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
@@ -1002,7 +1373,17 @@ | ||
const Versions = __webpack_require__(1); | ||
const MigrateCommons = __webpack_require__(2); | ||
/** Migrate processes related responses to the latest version. */ | ||
class MigrateProcesses { | ||
// Always returns a copy of the input process object | ||
static convertProcessToLatestSpec(originalProcess, version) { | ||
/** | ||
* Converts a `GET /process` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertProcessesToLatestSpec(response, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
@@ -1013,4 +1394,35 @@ throw "Migrating from API version 0.3.0 and older is not supported."; | ||
// Make sure we don't alter the original object | ||
let process = Utils.deepClone(originalProcess); | ||
response = Utils.deepClone(response); | ||
if (Array.isArray(response.processes)) { | ||
response.processes = response.processes | ||
.map(p => MigrateProcesses.convertProcessToLatestSpec(p, version)) | ||
.filter(p => typeof p.id === 'string'); | ||
} | ||
else { | ||
response.processes = []; | ||
} | ||
response.links = MigrateCommons.migrateLinks(response.links, version); | ||
return response; | ||
} | ||
/** | ||
* Converts a single process to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} process - The process to convert | ||
* @param {string} version - Version number of the API, which the process conforms to | ||
* @returns {object} | ||
*/ | ||
static convertProcessToLatestSpec(process, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
// Make sure we don't alter the original object | ||
process = Utils.deepClone(process); | ||
// If process has no id => seems to be an invalid process => abort | ||
@@ -1060,5 +1472,6 @@ if (typeof process.id !== 'string' || process.id.length === 0) { | ||
if (Array.isArray(process.parameters)) { | ||
for(let i in process.parameters) { | ||
for (var i = process.parameters.length-1; i >= 0; i--) { | ||
let param = process.parameters[i]; | ||
if (!Utils.isObject(param)) { | ||
process.parameters.splice(i, 1); | ||
continue; | ||
@@ -1086,2 +1499,11 @@ } | ||
// Remove process graphs from examples (and ensure there are arguments given) | ||
if (Array.isArray(process.examples)) { | ||
process.examples = process.examples.filter(example => Utils.isObject(example) && Utils.isObject(example.arguments)); | ||
} | ||
if (typeof process.links !== 'undefined') { // links not required, so only apply if defined anyway | ||
process.links = MigrateCommons.migrateLinks(process.links, version); | ||
} | ||
// Update process graph -> nothing to do yet | ||
@@ -1138,2 +1560,9 @@ | ||
// Clients SHOULD automatically set `optional` to `true`, if a default value is specified. | ||
if (Versions.compare(version, "0.4.x", ">")) { | ||
if (typeof obj.default !== 'undefined') { | ||
obj.optional = true; | ||
} | ||
} | ||
obj.schema = schema; | ||
@@ -1140,0 +1569,0 @@ return obj; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var r=t();for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=2)}([function(e,t){class r{static isObject(e){return"object"==typeof e&&e===Object(e)&&!Array.isArray(e)}static size(e){return"object"==typeof e&&null!==e?Array.isArray(e)?e.length:Object.keys(e).length:0}static isNumeric(e){return!isNaN(parseFloat(e))&&isFinite(e)}static deepClone(e){return JSON.parse(JSON.stringify(e))}static normalizeUrl(e,t=null){let r=e.replace(/\/$/,"");return"string"==typeof t&&("/"!==t.substr(0,1)&&(t="/"+t),r+=t.replace(/\/$/,"")),r}static replacePlaceholders(e,t={}){if("string"==typeof e&&r.isObject(t))for(var i in t){let r=t[i];e=e.replace("{"+i+"}",Array.isArray(r)?r.join("; "):r)}return e}}e.exports=r},function(e,t,r){const i=r(4);class n{static compare(e,t,r=null){return null!==r?i.compare(e,t,r):i(e,t)}static validate(e){return i.validate(e)}static findCompatible(e,t=!0,r=null,i=null){if(!Array.isArray(e)||0===e.length)return[];let s=e.filter(e=>{if("string"==typeof e.url&&n.validate(e.api_version)){let t=n.validate(r),s=n.validate(i);return t&&s?n.compare(e.api_version,r,">=")&&n.compare(e.api_version,i,"<="):t?n.compare(e.api_version,r,">="):!s||n.compare(e.api_version,i,"<=")}return!1});return 0===s.length?[]:s.sort((e,r)=>{let i=!0===e.production,s=!0===r.production;return t&&i!==s?i?-1:1:-1*n.compare(e.api_version,r.api_version)})}static findLatest(e,t=!0,r=null,i=null){let s=n.findCompatible(e,t,r,i);return s.length>0?s[0]:null}}e.exports=n},function(e,t,r){const i=r(3),n=r(5),s=r(6),a=r(1),o=r(0);e.exports={MigrateCapabilities:i,MigrateCollections:n,MigrateProcesses:s,Versions:a,Utils:o}},function(e,t,r){const i=r(0),n=r(1);e.exports=class{static guessApiVersion(e){if(!i.isObject(e))return"0.0.0";if(n.validate(e.api_version))return e.api_version;if(n.validate(e.version))return e.version;if(Array.isArray(e.endpoints)){if(e.endpoints.filter(e=>"/file_formats"===e.path||"/conformance"===e.path||"/files"===e.path).length>0)return"1.0.0";if(e.endpoints.filter(e=>"/output_formats"===e.path||"/files/{user_id}"===e.path).length>0)return"0.4.2";if(!(e.backend_version||e.title||e.description||e.links))return"0.3.1"}return"0.0.0"}static convertCapabilitiesToLatestSpec(e,t=null,r=!0,s=!0,a="unknown",o="Unknown",p="Unknown"){if(null===t&&(t=this.guessApiVersion(e)),"0.0.0"===t)return{};if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let l=i.deepClone(e);return l.api_version=r?"1.0.0":t,i.isObject(l.billing)?l.billing=this.convertBillingToLatestSpec(l.billing,t):delete l.billing,l.endpoints=this.convertEndpointsToLatestSpec(l.endpoints,t,s),!r&&n.compare(t,"0.4.x","=")?l.stac_version="0.6.2":(r||"string"!=typeof l.stac_version)&&(l.stac_version="0.9.0"),"boolean"!=typeof l.production&&(l.production=!(!n.compare(t,"1.0.0-rc.1","=")&&!n.compare(t,"1.0.0-rc.2","="))),"string"!=typeof l.backend_version&&(l.backend_version=p),"string"!=typeof l.id&&(l.id=a),"string"!=typeof l.title&&(l.title=o),"string"!=typeof l.description&&(l.description=""),Array.isArray(l.links)||(l.links=[]),l}static convertBillingToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r={};return i.isObject(e)&&(r=i.deepClone(e)),"string"!=typeof r.currency&&(r.currency=null),r}static convertEndpointsToLatestSpec(e,t,r=!1){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";if(!Array.isArray(e))return[];let s=i.deepClone(e);if(r){let e=n.compare(t,"0.4.x","="),r=n.compare(t,"1.0.0-rc.2","<"),i=function(e){let t="/process_graphs/{process_graph_id}",r=e.findIndex(e=>e.path===t);return r>=0?-1===e[r].methods.indexOf("PUT")&&e[r].methods.push("PUT"):e.push({path:t,methods:["PUT"]}),e};for(var a in s){let t=s[a];if(e)switch(t.path){case"/output_formats":t.path="/file_formats";break;case"/files/{user_id}":t.path="/files";break;case"/files/{user_id}/{path}":t.path="/files/{path}"}if(r)switch(t.path){case"/process_graphs":let e=t.methods.indexOf("POST");e>=0&&(t.methods.splice(e,1),i(s));break;case"/process_graphs/{process_graph_id}":let r=t.methods.indexOf("PATCH");r>=0&&(t.methods.splice(r,1),i(s))}}}return s}static convertOutputFormatsToLatestSpec(e,t){return this.convertFileFormatsToLatestSpec(e,t)}static convertFileFormatsToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r={};return i.isObject(e)&&(r=i.deepClone(e)),n.compare(t,"0.4.x","=")&&i.isObject(r)&&(r={output:r}),i.isObject(r.input)||(r.input={}),i.isObject(r.output)||(r.output={}),r}static convertServiceTypesToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r={};if(i.isObject(e)&&(r=i.deepClone(e)),n.compare(t,"0.4.x","="))for(let e in r)i.isObject(r[e])?(delete r[e].attributes,i.isObject(r[e].parameters)&&(r[e].configuration=r[e].parameters),delete r[e].parameters,Array.isArray(r[e].variables)&&(r[e].process_parameters=r[e].variables.map(e=>{let t={name:e.variable_id,description:"string"==typeof e.description?e.description:"",schema:{type:["string"==typeof e.type?e.type:"string","null"]}};return void 0!==e.default&&(t.default=e.default),t})),delete r[e].variables):r[e]={};return r}static convertUdfRuntimesToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r=i.deepClone(e);if(n.compare(t,"0.4.x","="))for(let e in r)i.isObject(r[e])?null===r[e].description&&(r[e].description=""):delete r[e];return r}}},function(e,t,r){var i,n,s;n=[],void 0===(s="function"==typeof(i=function(){var e=/^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;function t(e){var t,r,i=e.replace(/^v/,"").replace(/\+.*$/,""),n=(r="-",-1===(t=i).indexOf(r)?t.length:t.indexOf(r)),s=i.substring(0,n).split(".");return s.push(i.substring(n+1)),s}function r(e){return isNaN(Number(e))?e:Number(e)}function i(t){if("string"!=typeof t)throw new TypeError("Invalid argument expected string");if(!e.test(t))throw new Error("Invalid argument not valid semver ('"+t+"' received)")}function n(e,n){[e,n].forEach(i);for(var s=t(e),a=t(n),o=0;o<Math.max(s.length-1,a.length-1);o++){var p=parseInt(s[o]||0,10),l=parseInt(a[o]||0,10);if(p>l)return 1;if(l>p)return-1}var c=s[s.length-1],u=a[a.length-1];if(c&&u){var f=c.split(".").map(r),d=u.split(".").map(r);for(o=0;o<Math.max(f.length,d.length);o++){if(void 0===f[o]||"string"==typeof d[o]&&"number"==typeof f[o])return-1;if(void 0===d[o]||"string"==typeof f[o]&&"number"==typeof d[o])return 1;if(f[o]>d[o])return 1;if(d[o]>f[o])return-1}}else if(c||u)return c?-1:1;return 0}var s=[">",">=","=","<","<="],a={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]};return n.validate=function(t){return"string"==typeof t&&e.test(t)},n.compare=function(e,t,r){!function(e){if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===s.indexOf(e))throw new TypeError("Invalid operator, expected one of "+s.join("|"))}(r);var i=n(e,t);return a[r].indexOf(i)>-1},n})?i.apply(t,n):i)||(e.exports=s)},function(e,t,r){const i=r(0),n=r(1),s={cube:"datacube",eo:"eo",label:"label",pc:"pointcloud",proj:"projection",sar:"sar",sat:"sat",sci:"scientific",view:"view"},a={"item:license":"license","item:providers":"providers","eo:instrument":"instruments","eo:platform":"platform","eo:constellation":"constellation","eo:epsg":"proj:epsg","eo:off_nadir":"view:off_nadir","eo:azimuth":"view:azimuth","eo:sun_azimuth":"view:sun_azimuth","eo:sun_elevation":"view:sun_elevation","dtr:start_datetime":"start_datetime","dtr:end_datetime":"end_datetime","pc:schema":"pc:schemas","sar:type":"sar:product_type","sar:polarization":"sar:polarizations","sar:instrument":"instruments","sar:platform":"platform","sar:constellation":"constellation","sar:off_nadir":"sat:off_nadir_angle","sar:relative_orbit":"sat:relative_orbit","sar:pass_direction":"sat:orbit_state"},o=["cube:dimensions","sci:publications","sci:doi","sci:citation"];e.exports=class{static convertCollectionToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r=i.deepClone(e);if("string"!=typeof r.id||0===r.id.length)return{};if(n.validate(r.stac_version)&&!n.compare(r.stac_version,"0.9.0","<")||(r.stac_version="0.9.0"),i.isObject(r.extent)||(r.extent={}),n.compare(t,"0.4.x","=")){if(Array.isArray(r.extent.spatial)&&(r.extent.spatial={bbox:[r.extent.spatial]}),Array.isArray(r.extent.temporal)&&(r.extent.temporal={interval:[r.extent.temporal]}),i.isObject(r.properties)){i.isObject(r.other_properties)||(r.other_properties={});for(let e in r.properties)r.other_properties[e]={values:[r.properties[e]]}}delete r.properties;let e=i.isObject(r.other_properties)?r.other_properties:{};for(let t in e){let n=e[t];if(i.isObject(n)&&(Array.isArray(n.extent)||Array.isArray(n.values)))if(Array.isArray(n.extent))e[t]={min:n.extent[0],max:n.extent[1]};else{0===n.values.filter(e=>!Array.isArray(e)).length?n.values.length<2?e[t]=n.values[0]:e[t]=n.values.reduce((e,t)=>e.concat(t)):e[t]=n.values}else void 0===r[t]&&(r[t]=n),delete e[t]}delete r.other_properties,r.summaries=i.isObject(r.summaries)?r.summaries:{};for(let t in e){let i=e[t];"sar:pass_direction"===t&&(i=i.map(e=>null===e?"geostationary":e)),("sar:resolution"===t||"sar:pixel_spacing"===t||"sar:looks"===t)&&Array.isArray(i)&&i.length>=2?(r.summaries[t+"_range"]=i.slice(0,1),r.summaries[t+"_azimuth"]=i.slice(1,2),i.length>2&&(r.summaries[t+"_equivalent_number"]=i.slice(2,3))):"string"==typeof a[t]?r.summaries[a[t]]=i:o.includes(t)&&Array.isArray(i)&&1===i.length?r[t]=i[0]:r.summaries[t]=i}}"string"!=typeof r.description&&(r.description=""),i.isObject(r.extent.spatial)||(r.extent.spatial={}),i.isObject(r.extent.temporal)||(r.extent.temporal={}),"string"!=typeof r.license&&(r.license="proprietary"),i.isObject(r.summaries)||(r.summaries={}),i.isObject(r["cube:dimensions"])||(r["cube:dimensions"]={}),Array.isArray(r.links)||(r.links=[]),r.links=r.links.map(e=>(e.rel="string"==typeof e.rel?e.rel:"related",e));var p=Array.isArray(r.stac_extensions)?r.stac_extensions:[];for(var l in r){let e=null,t=l.split(":",1);"deprecated"===l||"version"===l?e="version":"string"==typeof s[t]&&(e=s[t]),null===e||p.includes(e)||p.push(e)}return p.sort(),r.stac_extensions=p,r}}},function(e,t,r){const i=r(0),n=r(1);function s(e,t,r=!0){var i={};if(e.schema&&"object"==typeof e.schema&&(i=e.schema),n.compare(t,"0.4.x","=")){for(let t of["anyOf","oneOf"])if(Array.isArray(i[t])){r&&void 0!==i.default&&(e.default=i.default),i=i[t];break}let s=n.compare(t,"0.4.x")<=0&&void 0!==e.media_type,o=Array.isArray(i)?i:[i];for(let t of o)t=a(t),r&&void 0!==t.default&&(e.default=t.default,delete t.default),s&&(t.contentMediaType=e.media_type);s&&delete e.media_type}return e.schema=i,e}function a(e){if(i.isObject(e)&&void 0!==e.type&&"string"==typeof e.format){switch(e.format){case"url":e.format="uri";break;case"proj-definition":e.deprecated=!0;break;case"callback":if(e.format="process-graph",i.isObject(e.parameters)){let t=[];for(let r in e.parameters){let i=e.parameters[r],n={name:r,description:"string"==typeof i.description?i.description:"",schema:i};t.push(n)}e.parameters=t}}e.subtype=e.format,["date-time","time","date","uri"].includes(e.format)||delete e.format}for(let t in e)e[t]&&"object"==typeof e[t]&&(e[t]=a(e[t]));return e}e.exports=class{static convertProcessToLatestSpec(e,t){if(n.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r=i.deepClone(e);if("string"!=typeof r.id||0===r.id.length)return{};if(n.compare(t,"0.4.x","=")){if(!Array.isArray(r.parameter_order)||0===r.parameter_order.length){r.parameter_order=[];for(let e in r.parameters)r.parameter_order.push(e)}let e=[];for(let t of r.parameter_order){let n={name:t};i.isObject(r.parameters[t])&&Object.assign(n,r.parameters[t]),n.required||(n.optional=!0),delete n.required,e.push(n)}delete r.parameter_order,r.parameters=e}if("string"!=typeof r.description&&(r.description=""),Array.isArray(r.parameters))for(let e in r.parameters){let n=r.parameters[e];i.isObject(n)&&("string"!=typeof n.description&&(n.description=""),r.parameters[e]=s(n,t))}else r.parameters=[];return i.isObject(r.returns)||(r.returns={}),r.returns=s(r.returns,t,!1),r}}}])})); | ||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var r=t();for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,r),s.l=!0,s.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)r.d(i,s,function(t){return e[t]}.bind(null,s));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=3)}([function(e,t){class r{static isObject(e){return"object"==typeof e&&e===Object(e)&&!Array.isArray(e)}static size(e){return"object"==typeof e&&null!==e?Array.isArray(e)?e.length:Object.keys(e).length:0}static isNumeric(e){return!isNaN(parseFloat(e))&&isFinite(e)}static deepClone(e){return JSON.parse(JSON.stringify(e))}static normalizeUrl(e,t=null){let r=e.replace(/\/$/,"");return"string"==typeof t&&("/"!==t.substr(0,1)&&(t="/"+t),r+=t.replace(/\/$/,"")),r}static replacePlaceholders(e,t={}){if("string"==typeof e&&r.isObject(t))for(var i in t){let r=t[i];e=e.replace("{"+i+"}",Array.isArray(r)?r.join("; "):r)}return e}static compareStringCaseInsensitive(e,t){return"string"!=typeof e&&(e=String(e)),"string"!=typeof t&&(t=String(t)),e.localeCompare(t,void 0,{numeric:!0,sensitivity:"base"})}static prettifyString(e,t="; "){return Array.isArray(e)||(e=[String(e)]),(e=e.map(e=>{if(e.length>=3){const t=(e,t,r)=>t+" "+r.toUpperCase();return(e=e.includes("_")?e.replace(/([a-zA-Z\d])_([a-zA-Z\d])/g,t):e.includes("-")?e.replace(/([a-zA-Z\d])-([a-zA-Z\d])/g,t):e.replace(/([a-z])([A-Z])/g,t)).charAt(0).toUpperCase()+e.substr(1)}return e})).join(t)}static friendlyLinks(e,t=!0,i=["self"]){let s=[];if(!Array.isArray(e))return s;for(let t of e)t=Object.assign({},t),"string"==typeof t.rel&&i.includes(t.rel.toLowerCase())||("string"==typeof t.title&&0!==t.title.length||("string"==typeof t.rel&&t.rel.length>1?t.title=r.prettifyString(t.rel):t.title=t.href.replace(/^https?:\/\/(www.)?/i,"").replace(/\/$/i,"")),s.push(t));return t&&s.sort((e,t)=>r.compareStringCaseInsensitive(e.title,t.title)),s}}e.exports=r},function(e,t,r){const i=r(5);class s{static compare(e,t,r=null){return null!==r?i.compare(e,t,r):i(e,t)}static validate(e){return i.validate(e)}static findCompatible(e,t=!0,r=null,i=null){if(!Array.isArray(e)||0===e.length)return[];let n=e.filter(e=>{if("string"==typeof e.url&&s.validate(e.api_version)){let t=s.validate(r),n=s.validate(i);return t&&n?s.compare(e.api_version,r,">=")&&s.compare(e.api_version,i,"<="):t?s.compare(e.api_version,r,">="):!n||s.compare(e.api_version,i,"<=")}return!1});return 0===n.length?[]:n.sort((e,r)=>{let i=!0===e.production,n=!0===r.production;return t&&i!==n?i?-1:1:-1*s.compare(e.api_version,r.api_version)})}static findLatest(e,t=!0,r=null,i=null){let n=s.findCompatible(e,t,r,i);return n.length>0?n[0]:null}}e.exports=s},function(e,t,r){const i=r(0),s=r(1);e.exports=class{static migrateLinks(e,t,r="related"){return Array.isArray(e)?e.filter(e=>i.isObject(e)&&"string"==typeof e.href).map(e=>("string"!=typeof e.rel&&(e.rel=r),e)):[]}static migrateDiscoveryParameters(e,t){if(s.compare(t,"1.0.0-rc.2","<="))for(var r in e){if(!i.isObject(e[r])){delete e[r];continue}let t=e[r].type;"string"==typeof t&&(e[r].type=[t,"null"]);let s=e[r].example;void 0!==s&&(e[r].examples=[s],delete e[r].example)}return e}}},function(e,t,r){const i=r(4),s=r(6),n=r(7),a=r(1),o=r(0);e.exports={MigrateCapabilities:i,MigrateCollections:s,MigrateProcesses:n,Versions:a,Utils:o}},function(e,t,r){const i=r(0),s=r(1),n=r(2);const a=["raster","vector","table","other"];function o(e,t){i.isObject(e)||(e={});for(let r in e)i.isObject(e[r].parameters)?e[r].parameters=n.migrateDiscoveryParameters(e[r].parameters,t):e[r].parameters={},Array.isArray(e[r].gis_data_types)?e[r].gis_data_types=e[r].gis_data_types.filter(e=>a.includes(e)):e[r].gis_data_types=[],void 0!==e[r].links&&(e[r].links=n.migrateLinks(e[r].links,t));return e}e.exports=class{static guessApiVersion(e){if(!i.isObject(e))return"0.0.0";if(s.validate(e.api_version))return e.api_version;if(s.validate(e.version))return e.version;if(Array.isArray(e.endpoints)){if(e.endpoints.filter(e=>"/file_formats"===e.path||"/conformance"===e.path||"/files"===e.path).length>0)return"1.0.0";if(e.endpoints.filter(e=>"/output_formats"===e.path||"/files/{user_id}"===e.path).length>0)return"0.4.2";if(!(e.backend_version||e.title||e.description||e.links))return"0.3.1"}return"0.0.0"}static convertCapabilitiesToLatestSpec(e,t=null,r=!0,a=!0,o="unknown",p="Unknown",l="0.0.0"){if(null===t&&(t=this.guessApiVersion(e)),"0.0.0"===t)return{};if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let c=i.deepClone(e);return c.api_version=r?"1.0.0":t,i.isObject(c.billing)?c.billing=this.convertBillingToLatestSpec(c.billing,t):delete c.billing,c.endpoints=this.convertEndpointsToLatestSpec(c.endpoints,t,a),!r&&s.compare(t,"0.4.x","=")?c.stac_version="0.6.2":(r||"string"!=typeof c.stac_version)&&(c.stac_version="0.9.0"),"boolean"!=typeof c.production&&(c.production=!(!s.compare(t,"1.0.0-rc.1","=")&&!s.compare(t,"1.0.0-rc.2","="))),"string"!=typeof c.backend_version&&(c.backend_version=l),"string"!=typeof c.id&&(c.id=o),"string"!=typeof c.title&&(c.title=p),"string"!=typeof c.description&&(c.description=""),c.links=n.migrateLinks(c.links,t),c}static convertBillingToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";return"string"!=typeof(e=i.isObject(e)?i.deepClone(e):{}).currency&&(e.currency=null),e}static convertEndpointsToLatestSpec(e,t,r=!1){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";if(!Array.isArray(e))return[];if(e=i.deepClone(e),r){let r=s.compare(t,"0.4.x","="),i=s.compare(t,"1.0.0-rc.2","<"),a=function(e){let t="/process_graphs/{process_graph_id}",r=e.findIndex(e=>e.path===t);return r>=0?-1===e[r].methods.indexOf("PUT")&&e[r].methods.push("PUT"):e.push({path:t,methods:["PUT"]}),e};for(var n in e){let t=e[n];if(r)switch(t.path){case"/output_formats":t.path="/file_formats";break;case"/files/{user_id}":t.path="/files";break;case"/files/{user_id}/{path}":t.path="/files/{path}"}if(i)switch(t.path){case"/process_graphs":let r=t.methods.indexOf("POST");r>=0&&(t.methods.splice(r,1),a(e));break;case"/process_graphs/{process_graph_id}":let i=t.methods.indexOf("PATCH");i>=0&&(t.methods.splice(i,1),a(e))}}}return e}static convertOutputFormatsToLatestSpec(e,t){return this.convertFileFormatsToLatestSpec(e,t)}static convertFileFormatsToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";return e=i.isObject(e)?i.deepClone(e):{},s.compare(t,"0.4.x","=")&&i.isObject(e)&&(e={output:e}),e.input=o(e.input,t),e.output=o(e.output,t),e}static convertServiceTypesToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";if(!i.isObject(e))return{};e=i.deepClone(e);for(let r in e)i.isObject(e[r])||(e[r]={}),s.compare(t,"0.4.x","=")&&(delete e[r].attributes,i.isObject(e[r].parameters)&&(e[r].configuration=e[r].parameters),delete e[r].parameters,Array.isArray(e[r].variables)&&(e[r].process_parameters=e[r].variables.map(e=>{let t={name:e.variable_id,description:"string"==typeof e.description?e.description:"",schema:{type:["string"==typeof e.type?e.type:"string","null"]}};return void 0!==e.default&&(t.default=e.default),t})),delete e[r].variables),i.isObject(e[r].configuration)?e[r].configuration=n.migrateDiscoveryParameters(e[r].configuration,t):e[r].configuration={},Array.isArray(e[r].process_parameters)||(e[r].process_parameters=[]),void 0!==e[r].links&&(e[r].links=n.migrateLinks(e[r].links,t));return e}static convertUdfRuntimesToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";if(!i.isObject(e))return{};e=i.deepClone(e);for(let r in e){if(s.compare(t,"0.4.x","=")){if(!i.isObject(e[r])){delete e[r];continue}null===e[r].description&&(e[r].description="")}"string"!=typeof e[r].type&&("string"==typeof e[r].docker?e[r].type="docker":e[r].type="language"),void 0!==e[r].links&&(e[r].links=n.migrateLinks(e[r].links,t))}return e}}},function(e,t,r){var i,s,n;s=[],void 0===(n="function"==typeof(i=function(){var e=/^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;function t(e){var t,r,i=e.replace(/^v/,"").replace(/\+.*$/,""),s=(r="-",-1===(t=i).indexOf(r)?t.length:t.indexOf(r)),n=i.substring(0,s).split(".");return n.push(i.substring(s+1)),n}function r(e){return isNaN(Number(e))?e:Number(e)}function i(t){if("string"!=typeof t)throw new TypeError("Invalid argument expected string");if(!e.test(t))throw new Error("Invalid argument not valid semver ('"+t+"' received)")}function s(e,s){[e,s].forEach(i);for(var n=t(e),a=t(s),o=0;o<Math.max(n.length-1,a.length-1);o++){var p=parseInt(n[o]||0,10),l=parseInt(a[o]||0,10);if(p>l)return 1;if(l>p)return-1}var c=n[n.length-1],u=a[a.length-1];if(c&&u){var f=c.split(".").map(r),d=u.split(".").map(r);for(o=0;o<Math.max(f.length,d.length);o++){if(void 0===f[o]||"string"==typeof d[o]&&"number"==typeof f[o])return-1;if(void 0===d[o]||"string"==typeof f[o]&&"number"==typeof d[o])return 1;if(f[o]>d[o])return 1;if(d[o]>f[o])return-1}}else if(c||u)return c?-1:1;return 0}var n=[">",">=","=","<","<="],a={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]};return s.validate=function(t){return"string"==typeof t&&e.test(t)},s.compare=function(e,t,r){!function(e){if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===n.indexOf(e))throw new TypeError("Invalid operator, expected one of "+n.join("|"))}(r);var i=s(e,t);return a[r].indexOf(i)>-1},s})?i.apply(t,s):i)||(e.exports=n)},function(e,t,r){const i=r(0),s=r(1),n=r(2),a={cube:"datacube",eo:"eo",label:"label",pc:"pointcloud",proj:"projection",sar:"sar",sat:"sat",sci:"scientific",view:"view"},o={"item:license":"license","item:providers":"providers","eo:instrument":"instruments","eo:platform":"platform","eo:constellation":"constellation","eo:epsg":"proj:epsg","eo:off_nadir":"view:off_nadir","eo:azimuth":"view:azimuth","eo:sun_azimuth":"view:sun_azimuth","eo:sun_elevation":"view:sun_elevation","dtr:start_datetime":"start_datetime","dtr:end_datetime":"end_datetime","pc:schema":"pc:schemas","sar:type":"sar:product_type","sar:polarization":"sar:polarizations","sar:instrument":"instruments","sar:platform":"platform","sar:constellation":"constellation","sar:off_nadir":"sat:off_nadir_angle","sar:relative_orbit":"sat:relative_orbit","sar:pass_direction":"sat:orbit_state"},p=["cube:dimensions","sci:publications","sci:doi","sci:citation"],l=["spatial","temporal","bands","other"];class c{static convertCollectionsToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";return e=i.deepClone(e),Array.isArray(e.collections)?e.collections=e.collections.map(e=>c.convertCollectionToLatestSpec(e,t)).filter(e=>"string"==typeof e.id):e.collections=[],e.links=n.migrateLinks(e.links,t),e}static convertCollectionToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";let r=i.deepClone(e);if("string"!=typeof r.id||0===r.id.length)return{};if(s.validate(r.stac_version)&&!s.compare(r.stac_version,"0.9.0","<")||(r.stac_version="0.9.0"),i.isObject(r.extent)||(r.extent={}),s.compare(t,"0.4.x","=")){if(Array.isArray(r.extent.spatial)&&(r.extent.spatial={bbox:[r.extent.spatial]}),Array.isArray(r.extent.temporal)&&(r.extent.temporal={interval:[r.extent.temporal]}),i.isObject(r.properties)){i.isObject(r.other_properties)||(r.other_properties={});for(let e in r.properties)r.other_properties[e]={values:[r.properties[e]]}}delete r.properties;let e=i.isObject(r.other_properties)?r.other_properties:{};for(let t in e){let s=e[t];if(i.isObject(s)&&(Array.isArray(s.extent)||Array.isArray(s.values)))if(Array.isArray(s.extent))e[t]={min:s.extent[0],max:s.extent[1]};else{0===s.values.filter(e=>!Array.isArray(e)).length?s.values.length<2?e[t]=s.values[0]:e[t]=s.values.reduce((e,t)=>e.concat(t)):e[t]=s.values}else void 0===r[t]&&(r[t]=s),delete e[t]}delete r.other_properties,i.isObject(r.summaries)||(r.summaries={});for(let t in e){let i=e[t];"sar:pass_direction"===t&&(i=i.map(e=>null===e?"geostationary":e)),("sar:resolution"===t||"sar:pixel_spacing"===t||"sar:looks"===t)&&Array.isArray(i)&&i.length>=2?(r.summaries[t+"_range"]=i.slice(0,1),r.summaries[t+"_azimuth"]=i.slice(1,2),i.length>2&&(r.summaries[t+"_equivalent_number"]=i.slice(2,3))):"string"==typeof o[t]?r.summaries[o[t]]=i:p.includes(t)&&Array.isArray(i)&&1===i.length?r[t]=i[0]:r.summaries[t]=i}}if("string"!=typeof r.description&&(r.description=""),i.isObject(r.extent.spatial)||(r.extent.spatial={}),i.isObject(r.extent.temporal)||(r.extent.temporal={}),"string"!=typeof r.license&&(r.license="proprietary"),i.isObject(r.summaries)||(r.summaries={}),i.isObject(r["cube:dimensions"]))for(var c in r["cube:dimensions"])i.isObject(r["cube:dimensions"][c])&&!l.includes(r["cube:dimensions"][c].type)&&(r["cube:dimensions"][c].type="other");else r["cube:dimensions"]={};r.links=n.migrateLinks(r.links);var u=Array.isArray(r.stac_extensions)?r.stac_extensions:[];for(var f in r){let e=null,t=f.split(":",1);"deprecated"===f||"version"===f?e="version":"string"==typeof a[t]&&(e=a[t]),null===e||u.includes(e)||u.push(e)}return u.sort(),r.stac_extensions=u,r}}e.exports=c},function(e,t,r){const i=r(0),s=r(1),n=r(2);class a{static convertProcessesToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";return e=i.deepClone(e),Array.isArray(e.processes)?e.processes=e.processes.map(e=>a.convertProcessToLatestSpec(e,t)).filter(e=>"string"==typeof e.id):e.processes=[],e.links=n.migrateLinks(e.links,t),e}static convertProcessToLatestSpec(e,t){if(s.compare(t,"0.3.x","<="))throw"Migrating from API version 0.3.0 and older is not supported.";if("string"!=typeof(e=i.deepClone(e)).id||0===e.id.length)return{};if(s.compare(t,"0.4.x","=")){if(!Array.isArray(e.parameter_order)||0===e.parameter_order.length){e.parameter_order=[];for(let t in e.parameters)e.parameter_order.push(t)}let t=[];for(let r of e.parameter_order){let s={name:r};i.isObject(e.parameters[r])&&Object.assign(s,e.parameters[r]),s.required||(s.optional=!0),delete s.required,t.push(s)}delete e.parameter_order,e.parameters=t}if("string"!=typeof e.description&&(e.description=""),Array.isArray(e.parameters))for(var r=e.parameters.length-1;r>=0;r--){let s=e.parameters[r];i.isObject(s)?("string"!=typeof s.description&&(s.description=""),e.parameters[r]=o(s,t)):e.parameters.splice(r,1)}else e.parameters=[];return i.isObject(e.returns)||(e.returns={}),e.returns=o(e.returns,t,!1),Array.isArray(e.examples)&&(e.examples=e.examples.filter(e=>i.isObject(e)&&i.isObject(e.arguments))),void 0!==e.links&&(e.links=n.migrateLinks(e.links,t)),e}}function o(e,t,r=!0){var i={};if(e.schema&&"object"==typeof e.schema&&(i=e.schema),s.compare(t,"0.4.x","=")){for(let t of["anyOf","oneOf"])if(Array.isArray(i[t])){r&&void 0!==i.default&&(e.default=i.default),i=i[t];break}let n=s.compare(t,"0.4.x")<=0&&void 0!==e.media_type,a=Array.isArray(i)?i:[i];for(let t of a)t=p(t),r&&void 0!==t.default&&(e.default=t.default,delete t.default),n&&(t.contentMediaType=e.media_type);n&&delete e.media_type}return s.compare(t,"0.4.x",">")&&void 0!==e.default&&(e.optional=!0),e.schema=i,e}function p(e){if(i.isObject(e)&&void 0!==e.type&&"string"==typeof e.format){switch(e.format){case"url":e.format="uri";break;case"proj-definition":e.deprecated=!0;break;case"callback":if(e.format="process-graph",i.isObject(e.parameters)){let t=[];for(let r in e.parameters){let i=e.parameters[r],s={name:r,description:"string"==typeof i.description?i.description:"",schema:i};t.push(s)}e.parameters=t}}e.subtype=e.format,["date-time","time","date","uri"].includes(e.format)||delete e.format}for(let t in e)e[t]&&"object"==typeof e[t]&&(e[t]=p(e[t]));return e}e.exports=a}])})); |
{ | ||
"name": "@openeo/js-commons", | ||
"version": "1.0.0-rc.4", | ||
"version": "1.0.0", | ||
"apiVersions": [ | ||
@@ -30,11 +30,11 @@ "0.4.x", | ||
"devDependencies": { | ||
"@babel/core": "^7.0.0", | ||
"jest": "^25.3.0", | ||
"@babel/core": "^7.10.5", | ||
"jest": "^25.5.4", | ||
"jest-html-reporter": "^3.1.3", | ||
"jsdoc": "^3.5.5", | ||
"jshint": "^2.10.2", | ||
"jsdoc": "^3.6.4", | ||
"jshint": "^2.11.1", | ||
"unminified-webpack-plugin": "^2.0.0", | ||
"webpack": "^4.42.1", | ||
"webpack-bundle-analyzer": "^3.7.0", | ||
"webpack-cli": "^3.3.11" | ||
"webpack": "^4.43.0", | ||
"webpack-bundle-analyzer": "^3.8.0", | ||
"webpack-cli": "^3.3.12" | ||
}, | ||
@@ -41,0 +41,0 @@ "dependencies": { |
@@ -5,10 +5,11 @@ # @openeo/js-commons | ||
This library's version is ![Version](https://img.shields.io/github/package-json/v/Open-EO/openeo-js-commons/dev) and supports ![Supported API Versions](https://img.shields.io/github/package-json/apiVersions/Open-Eo/openeo-js-commons/dev). | ||
The [master branch](https://github.com/Open-EO/openeo-api/tree/master) is the 'stable' version of library, which is currently version **1.0.0**. | ||
The [draft branch](https://github.com/Open-EO/openeo-api/tree/draft) is where active development takes place. | ||
This branch is the **development branch**, this library version is **unreleased** yet. | ||
[![Build Status](https://travis-ci.org/Open-EO/openeo-js-commons.svg?branch=master)](https://travis-ci.org/Open-EO/openeo-js-commons) | ||
![Dependencies](https://img.shields.io/librariesio/release/npm/@openeo/js-commons) | ||
![Minified Size](https://img.shields.io/bundlephobia/min/@openeo/js-commons/1.0.0) | ||
![Minzipped Size](https://img.shields.io/bundlephobia/minzip/@openeo/js-commons/1.0.0) | ||
![Supported API Versions](https://img.shields.io/github/package-json/apiVersions/Open-Eo/openeo-js-commons/master) | ||
[![Build Status](https://travis-ci.org/Open-EO/openeo-js-commons.svg?branch=dev)](https://travis-ci.org/Open-EO/openeo-js-commons) | ||
![Minified Size](https://img.shields.io/bundlephobia/min/@openeo/js-commons/1.0.0-rc.3) | ||
![Minzipped Size](https://img.shields.io/bundlephobia/minzip/@openeo/js-commons/1.0.0-rc.3) | ||
## Features | ||
@@ -38,6 +39,5 @@ - Converting responses from API version 0.4 to the latest API version is supported for: | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/@openeo/js-commons@1.0.0-rc.3/dist/main.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/@openeo/js-commons@1/dist/main.min.js"></script> | ||
``` | ||
<!-- When releasing a stable release, change the version to @1 instead of 1.0.0 to allow backward-compatible upgrades --> | ||
More information can be found in the [**JS commons documentation**](https://open-eo.github.io/openeo-js-commons/1.0.0-rc.3/). | ||
More information can be found in the [**JS commons documentation**](https://open-eo.github.io/openeo-js-commons/1.0.0/). |
const Utils = require('../utils.js'); | ||
const Versions = require('../versions.js'); | ||
const MigrateCommons = require('./commons.js'); | ||
const NO_VERSION = "0.0.0"; | ||
/** Migrate capabilities related responses to the latest version. */ | ||
class MigrateCapabilities { | ||
@@ -46,4 +48,17 @@ | ||
// Always returns a copy of the input object | ||
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "Unknown") { | ||
/** | ||
* Converts a `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string|null} version - Version number of the API, which the response conforms to. If `null`, tries to guess the version with `guessApiVersion()`. | ||
* @param {boolean} updateVersionNumbers - Should version numbers in the response be updated? | ||
* @param {boolean} updateEndpointPaths - Should the endpoint paths be updated to their recent equivalents? | ||
* @param {string} id - If no id is set in the response, sets it to the value specified here. Defaults to `unknown`. | ||
* @param {string} title - If no title is set in the response, sets it to the value specified here. Defaults to `Unknown`. | ||
* @param {string} title - If no backend_version is set in the response, sets it to the value specified here. Defaults to `0.0.0`. | ||
* @returns {object} | ||
*/ | ||
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "0.0.0") { | ||
if (version === null) { | ||
@@ -105,5 +120,3 @@ version = this.guessApiVersion(originalCapabilities); | ||
} | ||
if (!Array.isArray(capabilities.links)) { | ||
capabilities.links = []; | ||
} | ||
capabilities.links = MigrateCommons.migrateLinks(capabilities.links, version); | ||
@@ -113,11 +126,21 @@ return capabilities; | ||
// Always returns a copy of the input object | ||
static convertBillingToLatestSpec(originalBilling, version) { | ||
/** | ||
* Converts the billing part of the `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} billing - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertBillingToLatestSpec(billing, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let billing = {}; | ||
if (Utils.isObject(originalBilling)) { | ||
billing = Utils.deepClone(originalBilling); | ||
if (Utils.isObject(billing)) { | ||
billing = Utils.deepClone(billing); | ||
} | ||
else { | ||
billing = {}; | ||
} | ||
@@ -131,11 +154,20 @@ if (typeof billing.currency !== 'string') { | ||
// Always returns a copy of the input object | ||
static convertEndpointsToLatestSpec(originalEndpoints, version, updatePaths = false) { | ||
/** | ||
* Converts the endpoints part of the `GET /` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {array} endpoints - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @param {boolean} updatePaths - Should the endpoint paths be updated to their recent equivalents? | ||
* @returns {array} | ||
*/ | ||
static convertEndpointsToLatestSpec(endpoints, version, updatePaths = false) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
if (!Array.isArray(originalEndpoints)) { | ||
if (!Array.isArray(endpoints)) { | ||
return []; | ||
} | ||
let endpoints = Utils.deepClone(originalEndpoints); | ||
endpoints = Utils.deepClone(endpoints); | ||
// convert v0.4 endpoints to v1.0 | ||
@@ -201,16 +233,34 @@ if (updatePaths) { | ||
// Alias for convertFileFormatsToLatestSpec | ||
static convertOutputFormatsToLatestSpec(originalFormats, version) { | ||
return this.convertFileFormatsToLatestSpec(originalFormats, version); | ||
/** | ||
* Alias for `convertFileFormatsToLatestSpec()`. | ||
* | ||
* @alias MigrateCapabilities.convertFileFormatsToLatestSpec | ||
* @deprecated | ||
* @param {object} formats - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertOutputFormatsToLatestSpec(formats, version) { | ||
return this.convertFileFormatsToLatestSpec(formats, version); | ||
} | ||
// Always returns a copy of the input object | ||
static convertFileFormatsToLatestSpec(originalFormats, version) { | ||
/** | ||
* Converts a `GET /file_formats` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} formats - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertFileFormatsToLatestSpec(formats, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let formats = {}; | ||
if (Utils.isObject(originalFormats)) { | ||
formats = Utils.deepClone(originalFormats); | ||
if (Utils.isObject(formats)) { | ||
formats = Utils.deepClone(formats); | ||
} | ||
else { | ||
formats = {}; | ||
} | ||
@@ -223,8 +273,4 @@ if (Versions.compare(version, "0.4.x", "=") && Utils.isObject(formats)) { | ||
if (!Utils.isObject(formats.input)) { | ||
formats.input = {}; | ||
} | ||
if (!Utils.isObject(formats.output)) { | ||
formats.output = {}; | ||
} | ||
formats.input = upgradeFileFormats(formats.input, version); | ||
formats.output = upgradeFileFormats(formats.output, version); | ||
@@ -234,18 +280,25 @@ return formats; | ||
// Always returns a copy of the input object | ||
static convertServiceTypesToLatestSpec(originalTypes, version) { | ||
/** | ||
* Converts a `GET /service_types` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} types - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertServiceTypesToLatestSpec(types, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let types = {}; | ||
if (Utils.isObject(originalTypes)) { | ||
types = Utils.deepClone(originalTypes); | ||
if (!Utils.isObject(types)) { | ||
return {}; | ||
} | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
for(let t in types) { | ||
if (!Utils.isObject(types[t])) { | ||
types[t] = {}; | ||
continue; | ||
} | ||
types = Utils.deepClone(types); | ||
for(let t in types) { | ||
if (!Utils.isObject(types[t])) { | ||
types[t] = {}; | ||
} | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
// Remove attributes | ||
@@ -255,3 +308,2 @@ delete types[t].attributes; | ||
// Rename parameters to configuration | ||
if (Utils.isObject(types[t].parameters)) { | ||
@@ -283,2 +335,17 @@ types[t].configuration = types[t].parameters; | ||
} | ||
if (!Utils.isObject(types[t].configuration)) { | ||
types[t].configuration = {}; | ||
} | ||
else { | ||
types[t].configuration = MigrateCommons.migrateDiscoveryParameters(types[t].configuration, version); | ||
} | ||
if (!Array.isArray(types[t].process_parameters)) { | ||
types[t].process_parameters = []; | ||
} | ||
if (typeof types[t].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
types[t].links = MigrateCommons.migrateLinks(types[t].links, version); | ||
} | ||
} | ||
@@ -288,11 +355,23 @@ return types; | ||
// Always returns a copy of the input object | ||
static convertUdfRuntimesToLatestSpec(originalRuntimes, version) { | ||
/** | ||
* Converts a `GET /udf_runtimes` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} runtimes - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertUdfRuntimesToLatestSpec(runtimes, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
let runtimes = Utils.deepClone(originalRuntimes); | ||
if (!Utils.isObject(runtimes)) { | ||
return {}; | ||
} | ||
runtimes = Utils.deepClone(runtimes); | ||
for(let r in runtimes) { | ||
// Nothing to do, was not supported in 0.3 and nothing changed in 0.4. | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
for(let r in runtimes) { | ||
if (Versions.compare(version, "0.4.x", "=")) { | ||
if (!Utils.isObject(runtimes[r])) { | ||
@@ -308,3 +387,17 @@ delete runtimes[r]; | ||
} | ||
if (typeof runtimes[r].type !== 'string') { | ||
if (typeof runtimes[r].docker === 'string') { | ||
runtimes[r].type = 'docker'; | ||
} | ||
else { | ||
runtimes[r].type = 'language'; | ||
} | ||
} | ||
if (typeof runtimes[r].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
runtimes[r].links = MigrateCommons.migrateLinks(runtimes[r].links, version); | ||
} | ||
} | ||
return runtimes; | ||
@@ -315,2 +408,31 @@ } | ||
const GIS_DATA_TYPES = ['raster', 'vector', 'table', 'other']; | ||
function upgradeFileFormats(formats, version) { | ||
if (!Utils.isObject(formats)) { | ||
formats = {}; | ||
} | ||
for(let id in formats) { | ||
if (!Utils.isObject(formats[id].parameters)) { | ||
formats[id].parameters = {}; | ||
} | ||
else { | ||
formats[id].parameters = MigrateCommons.migrateDiscoveryParameters(formats[id].parameters, version); | ||
} | ||
// Can be empty: https://github.com/Open-EO/openeo-api/issues/325 | ||
if (!Array.isArray(formats[id].gis_data_types)) { | ||
formats[id].gis_data_types = []; | ||
} | ||
else { | ||
formats[id].gis_data_types = formats[id].gis_data_types.filter(t => GIS_DATA_TYPES.includes(t)); | ||
} | ||
if (typeof formats[id].links !== 'undefined') { // links not required, so only apply if defined anyway | ||
formats[id].links = MigrateCommons.migrateLinks(formats[id].links, version); | ||
} | ||
} | ||
return formats; | ||
} | ||
module.exports = MigrateCapabilities; |
const Utils = require('../utils.js'); | ||
const Versions = require('../versions.js'); | ||
const MigrateCommons = require('./commons.js'); | ||
@@ -60,5 +61,53 @@ const extMap = { | ||
const DIMENSION_TYPES = [ | ||
'spatial', | ||
'temporal', | ||
'bands', | ||
'other' | ||
]; | ||
/** Migrate Collections related responses to the latest version. */ | ||
class MigrateCollections { | ||
// Always returns a copy of the input collection object | ||
/** | ||
* Converts a `GET /collections` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertCollectionsToLatestSpec(response, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
// Make sure we don't alter the original object | ||
response = Utils.deepClone(response); | ||
if (Array.isArray(response.collections)) { | ||
response.collections = response.collections | ||
.map(c => MigrateCollections.convertCollectionToLatestSpec(c, version)) | ||
.filter(c => typeof c.id === 'string'); | ||
} | ||
else { | ||
response.collections = []; | ||
} | ||
response.links = MigrateCommons.migrateLinks(response.links, version); | ||
return response; | ||
} | ||
/** | ||
* Converts a single collection to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} process - The collection to convert | ||
* @param {string} version - Version number of the API, which the collection conforms to | ||
* @returns {object} | ||
*/ | ||
static convertCollectionToLatestSpec(originalCollection, version) { | ||
@@ -157,3 +206,5 @@ if (Versions.compare(version, "0.3.x", "<=")) { | ||
collection.summaries = Utils.isObject(collection.summaries) ? collection.summaries : {}; | ||
if (!Utils.isObject(collection.summaries)) { | ||
collection.summaries = {}; | ||
} | ||
for(let key in props) { | ||
@@ -209,12 +260,12 @@ let val = props[key]; | ||
} | ||
else { | ||
for(var name in collection['cube:dimensions']) { | ||
if (Utils.isObject(collection['cube:dimensions'][name]) && !DIMENSION_TYPES.includes(collection['cube:dimensions'][name].type)) { | ||
collection['cube:dimensions'][name].type = 'other'; | ||
} | ||
} | ||
} | ||
// Fix links | ||
if (!Array.isArray(collection.links)) { | ||
collection.links = []; | ||
} | ||
// Add missing rel type | ||
collection.links = collection.links.map(l => { | ||
l.rel = typeof l.rel === 'string' ? l.rel : "related"; | ||
return l; | ||
}); | ||
collection.links = MigrateCommons.migrateLinks(collection.links); | ||
@@ -221,0 +272,0 @@ // Fix stac_extensions |
const Utils = require('../utils.js'); | ||
const Versions = require('../versions.js'); | ||
const MigrateCommons = require('./commons.js'); | ||
/** Migrate processes related responses to the latest version. */ | ||
class MigrateProcesses { | ||
// Always returns a copy of the input process object | ||
static convertProcessToLatestSpec(originalProcess, version) { | ||
/** | ||
* Converts a `GET /process` response to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} response - The response to convert | ||
* @param {string} version - Version number of the API, which the response conforms to | ||
* @returns {object} | ||
*/ | ||
static convertProcessesToLatestSpec(response, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
@@ -13,4 +23,35 @@ throw "Migrating from API version 0.3.0 and older is not supported."; | ||
// Make sure we don't alter the original object | ||
let process = Utils.deepClone(originalProcess); | ||
response = Utils.deepClone(response); | ||
if (Array.isArray(response.processes)) { | ||
response.processes = response.processes | ||
.map(p => MigrateProcesses.convertProcessToLatestSpec(p, version)) | ||
.filter(p => typeof p.id === 'string'); | ||
} | ||
else { | ||
response.processes = []; | ||
} | ||
response.links = MigrateCommons.migrateLinks(response.links, version); | ||
return response; | ||
} | ||
/** | ||
* Converts a single process to the latest version. | ||
* | ||
* Always returns a deep copy of the input object. | ||
* | ||
* @param {object} process - The process to convert | ||
* @param {string} version - Version number of the API, which the process conforms to | ||
* @returns {object} | ||
*/ | ||
static convertProcessToLatestSpec(process, version) { | ||
if (Versions.compare(version, "0.3.x", "<=")) { | ||
throw "Migrating from API version 0.3.0 and older is not supported."; | ||
} | ||
// Make sure we don't alter the original object | ||
process = Utils.deepClone(process); | ||
// If process has no id => seems to be an invalid process => abort | ||
@@ -60,5 +101,6 @@ if (typeof process.id !== 'string' || process.id.length === 0) { | ||
if (Array.isArray(process.parameters)) { | ||
for(let i in process.parameters) { | ||
for (var i = process.parameters.length-1; i >= 0; i--) { | ||
let param = process.parameters[i]; | ||
if (!Utils.isObject(param)) { | ||
process.parameters.splice(i, 1); | ||
continue; | ||
@@ -86,2 +128,11 @@ } | ||
// Remove process graphs from examples (and ensure there are arguments given) | ||
if (Array.isArray(process.examples)) { | ||
process.examples = process.examples.filter(example => Utils.isObject(example) && Utils.isObject(example.arguments)); | ||
} | ||
if (typeof process.links !== 'undefined') { // links not required, so only apply if defined anyway | ||
process.links = MigrateCommons.migrateLinks(process.links, version); | ||
} | ||
// Update process graph -> nothing to do yet | ||
@@ -138,2 +189,9 @@ | ||
// Clients SHOULD automatically set `optional` to `true`, if a default value is specified. | ||
if (Versions.compare(version, "0.4.x", ">")) { | ||
if (typeof obj.default !== 'undefined') { | ||
obj.optional = true; | ||
} | ||
} | ||
obj.schema = schema; | ||
@@ -140,0 +198,0 @@ return obj; |
122
src/utils.js
@@ -0,1 +1,2 @@ | ||
/** General utilities */ | ||
class Utils { | ||
@@ -16,2 +17,10 @@ | ||
/** | ||
* Computes the size of an array (number of array elements) or object (number of key-value-pairs). | ||
* | ||
* Returns 0 for all other data types. | ||
* | ||
* @param {*} obj | ||
* @returns {integer} | ||
*/ | ||
static size(obj) { | ||
@@ -44,4 +53,4 @@ if (typeof obj === 'object' && obj !== null) { | ||
* | ||
* @param {*} x | ||
* @returns {*} | ||
* @param {*} x - The data to clone. | ||
* @returns {*} - The cloned data. | ||
*/ | ||
@@ -53,3 +62,3 @@ static deepClone(x) { | ||
/** | ||
* Normalize a URL (mostly handling slashes). | ||
* Normalize a URL (mostly handling leading and trailing slashes). | ||
* | ||
@@ -72,2 +81,10 @@ * @static | ||
/** | ||
* Replaces placeholders in this format: `{var}`. | ||
* | ||
* This can be used for the placeholders/variables in the openEO API's errors.json file. | ||
* | ||
* @param {string} message - The string to replace the placeholders in. | ||
* @param {object} variables - A map with the placeholder names as keys and the replacement value as value. | ||
*/ | ||
static replacePlaceholders(message, variables = {}) { | ||
@@ -83,4 +100,103 @@ if (typeof message === 'string' && Utils.isObject(variables)) { | ||
/** | ||
* Compares two strings case-insensitive, including natural ordering for numbers. | ||
* | ||
* @param {string} a | ||
* @param {string} b | ||
* @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). | ||
*/ | ||
static compareStringCaseInsensitive(a, b) { | ||
if (typeof a !== 'string') { | ||
a = String(a); | ||
} | ||
if (typeof b !== 'string') { | ||
b = String(b); | ||
} | ||
return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'}); | ||
} | ||
/** | ||
* Tries to make a string more readable by capitalizing it. | ||
* Only applies to words with more than two characters. | ||
* | ||
* Supports converting from: | ||
* - Snake Case (abc_def => Abc Def) | ||
* - Kebab Case (abc-def => Abc Def) | ||
* - Camel Case (abcDef => Abc Def) | ||
* | ||
* Doesn't capitalize if the words are not in any of the casing formats above. | ||
* | ||
* @param {*} strings - String(s) to make readable | ||
* @param {string} arraySep - String to separate array elements with | ||
* @returns {string} | ||
*/ | ||
static prettifyString(strings, arraySep = '; ') { | ||
if (!Array.isArray(strings)) { | ||
strings = [String(strings)]; | ||
} | ||
strings = strings.map(str => { | ||
if (str.length >= 3) { | ||
const replacer = (_,a,b) => a + ' ' + b.toUpperCase(); | ||
if (str.includes('_')) { | ||
// Snake case converter | ||
str = str.replace(/([a-zA-Z\d])_([a-zA-Z\d])/g, replacer); | ||
} | ||
else if (str.includes('-')) { | ||
// Kebab case converter | ||
str = str.replace(/([a-zA-Z\d])-([a-zA-Z\d])/g, replacer); | ||
} | ||
else { | ||
// Camelcase converter | ||
str = str.replace(/([a-z])([A-Z])/g, replacer); | ||
} | ||
// Uppercase the first letter in the first word, too. | ||
return str.charAt(0).toUpperCase() + str.substr(1); | ||
} | ||
return str; | ||
}); | ||
return strings.join(arraySep); | ||
} | ||
/** | ||
* Makes link lists from the openEO API more user-friendly. | ||
* | ||
* Supports: | ||
* - Set a reasonable title, if not available. Make title more readable. | ||
* - Sorting by title (see `sort` parameter) | ||
* - Removing given relation types (`rel` property, see `ignoreRel` parameter) | ||
* | ||
* @param {array} linkList - List of links | ||
* @param {boolean} sort - Enable/Disable sorting by title. Enabled (true) by default. | ||
* @param {array} ignoreRel - A list of rel types to remove. By default, removes the self links (rel type = `self`). | ||
* @returns {array} | ||
*/ | ||
static friendlyLinks(linkList, sort = true, ignoreRel = ['self']) { | ||
let links = []; | ||
if (!Array.isArray(linkList)) { | ||
return links; | ||
} | ||
for(let link of linkList) { | ||
link = Object.assign({}, link); // Make sure to work on a copy | ||
if (typeof link.rel === 'string' && ignoreRel.includes(link.rel.toLowerCase())) { | ||
continue; | ||
} | ||
if (typeof link.title !== 'string' || link.title.length === 0) { | ||
if (typeof link.rel === 'string' && link.rel.length > 1) { | ||
link.title = Utils.prettifyString(link.rel); | ||
} | ||
else { | ||
link.title = link.href.replace(/^https?:\/\/(www.)?/i, '').replace(/\/$/i, ''); | ||
} | ||
} | ||
links.push(link); | ||
} | ||
if (sort) { | ||
links.sort((a, b) => Utils.compareStringCaseInsensitive(a.title, b.title)); | ||
} | ||
return links; | ||
} | ||
} | ||
module.exports = Utils; |
const VersionCompare = require('compare-versions'); | ||
/** Version Number related methods */ | ||
class Versions { | ||
/** | ||
* Compare [semver](https://semver.org/) version strings. | ||
* | ||
* @param {string} firstVersion First version to compare | ||
* @param {string} secondVersion Second version to compare | ||
* @param {string|null} operator Optional; Arithmetic operator to use (>, >=, =, <=, <, !=). Defaults to `null`. | ||
* @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). | ||
* ``` | ||
*/ | ||
static compare(v1, v2, operator = null) { | ||
@@ -14,2 +24,8 @@ if (operator !== null) { | ||
/** | ||
* Validate [semver](https://semver.org/) version strings. | ||
* | ||
* @param {*} version - Version number to validate | ||
* @returns - `true` if the version number is a valid semver version number, `false` otherwise. | ||
*/ | ||
static validate(version) { | ||
@@ -24,2 +40,5 @@ return VersionCompare.validate(version); | ||
* @param {array} wkVersions - A well-known discovery document compliant to the API specification. | ||
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions. | ||
* @param {string|null} minVersion - The minimum version that should be returned. | ||
* @param {string|null} maxVersion - The maximum version that should be returned. | ||
* @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable. | ||
@@ -70,2 +89,13 @@ */ | ||
/** | ||
* Find the latest version from well-known discovery that applies to the specified rules. | ||
* | ||
* This is basically the same as calling `findCompatible` and using the first element from the result. | ||
* | ||
* @param {array} wkVersions - A well-known discovery document compliant to the API specification. | ||
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions. | ||
* @param {string|null} minVersion - The minimum version that should be returned. | ||
* @param {string|null} maxVersion - The maximum version that should be returned. | ||
* @returns {object|null} | ||
*/ | ||
static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) { | ||
@@ -72,0 +102,0 @@ let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion); |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
135909
12
2588
0