New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@openeo/js-commons

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openeo/js-commons - npm Package Compare versions

Comparing version 0.5.0-alpha.1 to 1.0.0-rc.1

src/versions.js

2345

dist/main.js
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory((function webpackLoadOptionalExternalModule() { try { return require("ajv"); } catch(e) {} }()));
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define(["ajv"], factory);
define([], factory);
else {
var a = typeof exports === 'object' ? factory((function webpackLoadOptionalExternalModule() { try { return require("ajv"); } catch(e) {} }())) : factory(root["ajv"]);
var a = factory();
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(window, function(__WEBPACK_EXTERNAL_MODULE__12__) {
})(window, function() {
return /******/ (function(modules) { // webpackBootstrap

@@ -94,3 +94,3 @@ /******/ // The module cache

/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ return __webpack_require__(__webpack_require__.s = 2);
/******/ })

@@ -100,42 +100,61 @@ /************************************************************************/

/* 0 */
/***/ (function(module, exports, __webpack_require__) {
/***/ (function(module, exports) {
const compareVersions = __webpack_require__(9);
class Utils {
var Utils = {
/**
* Checks whether a variable is a real object or not.
*
* This is a more strict version of `typeof x === 'object'` as this example would also succeeds for arrays and `null`.
* This function only returns `true` for real objects and not for arrays, `null` or any other data types.
*
* @param {*} obj - A variable to check.
* @returns {boolean} - `true` is the given variable is an object, `false` otherwise.
*/
static isObject(obj) {
return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
}
compareVersion(v1, v2) {
try {
return compareVersions(v1, v2);
} catch (error) {
return null;
}
},
/**
* Checks whether a variable is numeric.
*
* Numeric is every string with numeric data or a number, excluding NaN and finite numbers.
*
* @param {*} n - A variable to check.
* @returns {boolean} - `true` is the given variable is numeric, `false` otherwise.
*/
static isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
/**
* Deep clone for JSON-compatible data.
*
* @param {*} x
* @returns {*}
*/
static deepClone(x) {
return JSON.parse(JSON.stringify(x));
}
isObject(obj) {
return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
},
size(obj) {
if (typeof obj === 'object' && obj !== null) {
if (Array.isArray(obj)) {
return obj.length;
/**
* Normalize a URL (mostly handling slashes).
*
* @static
* @param {string} baseUrl - The URL to normalize
* @param {string} path - An optional path to add to the URL
* @returns {string} Normalized URL.
*/
static normalizeUrl(baseUrl, path = null) {
let url = baseUrl.replace(/\/$/, ""); // Remove trailing slash from base URL
if (typeof path === 'string') {
if (path.substr(0, 1) !== '/') {
path = '/' + path; // Add leading slash to path
}
else {
return Object.keys(obj).length;
}
url = url + path.replace(/\/$/, ""); // Remove trailing slash from path
}
return 0;
},
replacePlaceholders(message, variables = {}) {
if (typeof message === 'string' && this.isObject(variables)) {
for(var placeholder in variables) {
message = message.replace('{' + placeholder + '}', variables[placeholder]);
}
}
return message;
return url;
}
};
}

@@ -148,1236 +167,100 @@ module.exports = Utils;

const Utils = __webpack_require__(0);
const VersionCompare = __webpack_require__(4);
const MESSAGES = {
"MultipleResultNodes": "Multiple result nodes specified for process graph.",
"StartNodeMissing": "No start nodes found for process graph.",
"ResultNodeMissing": "No result node found for process graph.",
"MultipleResultNodesCallback": "Multiple result nodes specified for the callback in the process '{process_id}' (node: '{node_id}').",
"StartNodeMissingCallback": "No start nodes found for the callback in the process '{process_id}' (node: '{node_id}')'.",
"ResultNodeMissingCallback": "No result node found for the callback in the process '{process_id}' (node: '{node_id}').",
"ReferencedNodeMissing": "Referenced node '{node_id}' doesn't exist.",
"NodeIdInvalid": "Invalid node id specified in process graph.",
"NodeInvalid": "Process graph node '{node_id}' is not a valid object.",
"ProcessIdMissing": "Process graph node '{node_id}' doesn't contain a process id.",
"CallbackArgumentInvalid": "Invalid callback argument '{argument}' requested in the process '{process_id}' (node: '{node_id}').",
"ProcessUnsupported": "Process '{process}' is not supported.",
"ProcessArgumentUnsupported": "Process '{process}' does not support argument '{argument}'.",
"ProcessArgumentRequired": "Process '{process}' requires argument '{argument}'.",
"ProcessArgumentInvalid": "The argument '{argument}' in process '{process}' is invalid: {reason}",
"VariableValueMissing": "No value specified for process graph variable '{variable_id}'.",
"VariableDefaultValueTypeInvalid": "The default value specified for the process graph variable '{variable_id}' is not of type '{type}'.",
"VariableValueTypeInvalid": "The value specified for the process graph variable '{variable_id}' is not of type '{type}'.",
"VariableIdInvalid": "A specified variable ID is not valid.",
"VariableTypeInvalid": "The data type specified for the process graph variable '{variable_id}' is invalid. Must be one of: string, boolean, number, array or object.",
};
const semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
module.exports = class ProcessGraphError extends Error {
class Versions {
constructor(codeOrMsg, variables = {}) {
super();
this.variables = variables;
if (typeof MESSAGES[codeOrMsg] === 'string') {
this.code = codeOrMsg;
this.message = Utils.replacePlaceholders(MESSAGES[codeOrMsg], variables);
static compare(v1, v2, operator = null) {
if (operator !== null) {
return VersionCompare.compare(v1, v2, operator);
}
else {
this.code = codeOrMsg.replace(/[^\w\d]+/g, '');
this.message = codeOrMsg;
return VersionCompare(v1, v2);
}
}
toJSON() {
return {
code: this.code,
message: this.message
};
}
};
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
const ProcessGraphError = __webpack_require__(1);
const Utils = __webpack_require__(0);
module.exports = class ProcessGraphNode {
constructor(json, id, parent) {
if (typeof id !== 'string' || id.length === 0) {
throw new ProcessGraphError('NodeIdInvalid');
// Function or regexp is coming from compare-version, but not exposed so copied it here.
// See also https://github.com/omichelsen/compare-versions/issues/37
static validate(version) {
if (typeof version !== 'string') {
return false;
}
if (!Utils.isObject(json)) {
throw new ProcessGraphError('NodeInvalid', {node_id: id});
}
if (typeof json.process_id !== 'string') {
throw new ProcessGraphError('ProcessIdMissing', {node_id: id});
}
this.id = id;
this.processGraph = parent;
this.process_id = json.process_id;
this.arguments = Utils.isObject(json.arguments) ? JSON.parse(JSON.stringify(json.arguments)) : {};
this.description = json.description || null;
this.isResultNode = json.result || false;
this.expectsFrom = [];
this.passesTo = [];
this.result = null;
this.resultsAvailableFrom = [];
return semver.test(version);
}
getProcessGraph() {
return this.processGraph;
}
getArgumentNames() {
return Object.keys(this.arguments);
}
hasArgument(name) {
return (name in this.arguments);
}
getArgumentType(name) {
return ProcessGraphNode.getType(this.arguments[name]);
}
getRawArgument(name) {
return this.arguments[name];
}
getRawArgumentValue(name) {
var arg = this.arguments[name];
switch(ProcessGraphNode.getType(arg)) {
case 'result':
return arg.from_node;
case 'callback':
return arg.callback;
case 'callback-argument':
return arg.from_argument;
default:
return arg;
}
}
getArgument(name, defaultValue = undefined) {
if (typeof this.arguments[name] === 'undefined') {
return defaultValue;
}
return this.processArgument(this.arguments[name]);
}
processArgument(arg) {
var type = ProcessGraphNode.getType(arg);
switch(type) {
case 'result':
return this.processGraph.getNode(arg.from_node).getResult();
case 'callback':
return arg.callback;
case 'callback-argument':
return this.processGraph.getParameter(arg.from_argument);
case 'variable':
return this.processGraph.getVariableValue(arg.variable_id);
case 'array':
case 'object':
for(var i in arg) {
arg[i] = this.processArgument(arg[i]);
}
return arg;
default:
return arg;
}
}
static getType(obj, reportNullAs = 'null') {
if (typeof obj === 'object') {
if (obj === null) {
return reportNullAs;
}
else if (Array.isArray(obj)) {
return 'array';
}
else if(obj.hasOwnProperty("callback")) {
return 'callback';
}
else if(obj.hasOwnProperty("variable_id")) {
return 'variable';
}
else if(obj.hasOwnProperty("from_node")) {
return 'result';
}
else if(obj.hasOwnProperty("from_argument")) {
return 'callback-argument';
}
else {
return 'object';
}
}
return (typeof obj);
}
isStartNode() {
return (this.expectsFrom.length === 0);
}
addPreviousNode(node) {
this.expectsFrom.push(node);
}
getPreviousNodes() {
return this.expectsFrom;
}
addNextNode(node) {
this.passesTo.push(node);
}
getNextNodes() {
return this.passesTo;
}
reset() {
this.result = null;
this.resultsAvailableFrom = [];
}
setDescription(description) {
if (typeof description === 'string') {
this.description = description;
}
else {
this.description = null;
}
}
setResult(result) {
this.result = result;
}
getResult() {
return this.result;
}
solveDependency(dependencyNode) {
if (dependencyNode !== null && this.expectsFrom.includes(dependencyNode)) {
this.resultsAvailableFrom.push(dependencyNode);
}
return (this.expectsFrom.length === this.resultsAvailableFrom.length); // all dependencies solved?
}
};
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
const JsonSchemaValidator = __webpack_require__(4);
const ProcessGraphError = __webpack_require__(1);
const ProcessGraphNode = __webpack_require__(2);
const ProcessGraph = __webpack_require__(5);
module.exports = class BaseProcess {
constructor(schema, validator = null) {
this.schema = schema;
if (validator === null) {
this.jsonSchema = new JsonSchemaValidator();
}
else {
this.jsonSchema = validator;
}
}
async validate(node) {
// Check for arguments we don't support and throw error
var unsupportedArgs = node.getArgumentNames().filter(name => (typeof this.schema.parameters[name] === 'undefined'));
if (unsupportedArgs.length > 0) {
throw new ProcessGraphError('ProcessArgumentUnsupported', {
process: this.schema.id,
argument: unsupportedArgs[0]
});
}
// Validate against JSON Schema
for(let name in this.schema.parameters) {
let param = this.schema.parameters[name];
let arg = node.getRawArgument(name);
if (await this.validateArgument(arg, node, name, param)) {
continue;
}
// Validate against JSON schema
let errors = await this.jsonSchema.validateJson(arg, param.schema);
if (errors.length > 0) {
throw new ProcessGraphError('ProcessArgumentInvalid', {
process: this.schema.id,
argument: name,
reason: errors.join("; ")
});
}
}
}
async validateArgument(arg, node, parameterName, param) {
let argType = ProcessGraphNode.getType(arg);
if (arg instanceof ProcessGraph) {
await arg.validate(true);
return true;
}
switch(argType) {
// Check whether parameter is required
case 'undefined':
if (param.required) {
throw new ProcessGraphError('ProcessArgumentRequired', {
process: this.schema.id,
argument: parameterName
});
}
return true; // Parameter not set, nothing to validate against
case 'callback-argument':
var cbParams = node.getProcessGraph().getCallbackParameters();
// No need for further checks, callback argument is validated in processgraph.js: see parseCallbackArgument()
return JsonSchemaValidator.isSchemaCompatible(param.schema, cbParams[arg.from_argument]);
case 'variable':
var variableSchema = {
type: arg.type || 'string'
};
return JsonSchemaValidator.isSchemaCompatible(param.schema, variableSchema);
case 'result':
try {
var pg = node.getProcessGraph();
var process_id = pg.getNode(arg.from_node).process_id;
var process = pg.getProcess(process_id);
return JsonSchemaValidator.isSchemaCompatible(param.schema, process.schema.returns.schema);
} catch (e) {}
break;
case 'array':
case 'object':
// ToDo: Check how we can validate arrays and objects that have references to callback arguments, variables and node results in them...
// See issue https://github.com/Open-EO/openeo-js-commons/issues/5
// for(var i in arg) {
// await this.validateArgument(arg[i], node, parameterName, param);
// }
return true;
}
return false;
}
/* istanbul ignore next */
async execute(/*node*/) {
throw "execute not implemented yet";
}
/* istanbul ignore next */
test() {
// Run the tests from the examples
throw "test not implemented yet";
}
};
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
var ajv;
try {
ajv = __webpack_require__(12);
} catch(err) {}
const Utils = __webpack_require__(0);
module.exports = class JsonSchemaValidator {
constructor() {
this.typeHints = {
'band-name': {type: 'string', validate: 'validateBandName'},
'bounding-box': {type: 'object', validate: 'validateBoundingBox'},
'callback': {type: 'object', validate: 'validateCallback'},
'collection-id': {type: 'string', validate: 'validateCollectionId'},
'epsg-code': {type: 'integer', validate: 'validateEpsgCode'},
'geojson': {type: 'object', validate: 'validateGeoJson'},
'job-id': {type: 'string', validate: 'validateJobId'},
'kernel': {type: 'array', validate: 'validateKernel'},
'output-format': {type: 'string', validate: 'validateOutputFormat'},
'output-format-options': {type: 'object', validate: 'validateOutputFormatOptions'},
'process-graph-id': {type: 'string', validate: 'validateProcessGraphId'},
'process-graph-variables': {type: 'object', validate: 'validateProcessGraphVariables'},
'proj-definition': {type: 'string', validate: 'validateProjDefinition'}, // Proj is deprecated. Implement projjson and wkt2 instead
'raster-cube': {type: 'object', validate: 'validateRasterCube'},
'temporal-interval': {type: 'array', validate: 'validateTemporalInterval'},
'temporal-intervals': {type: 'array', validate: 'validateTemporalIntervals'},
'vector-cube': {type: 'object', validate: 'validateVectorCube'}
};
var ajvOptions = {
schemaId: 'auto',
format: 'full',
unknownFormats: Object.keys(this.typeHints)
};
if (!ajv) {
throw "ajv not installed";
}
this.ajv = new ajv(ajvOptions);
this.ajv.addKeyword('parameters', {
dependencies: [
"type",
"format"
],
metaSchema: {
type: "object",
additionalProperties: {
type: "object"
}
},
valid: true,
errors: true
});
this.ajv.addKeyword('typehint', {
dependencies: [
"type"
],
validate: async (typehint, data, schema) => {
if (typeof this.typeHints[typehint] === 'object') {
var th = this.typeHints[typehint];
if (th.type === schema.type || (Array.isArray(schema.type) && schema.type.includes(th.type))) {
return await this[th.validate](data);
}
}
return false;
},
async: true,
errors: true
});
this.outputFormats = null;
this.geoJsonValidator = null;
}
/* This is a temporary workaround for the following issues:
- https://github.com/epoberezkin/ajv/issues/1039
- https://github.com/Open-EO/openeo-processes/issues/67
Once one of the issues is solved, fixSchema can be removed.
*/
fixSchemaFormat(s) {
for(var i in s) {
if (i === 'format' && typeof s[i] === 'string' && Object.keys(this.typeHints).includes(s[i])) {
s.typehint = s[i];
}
if (s[i] && typeof s[i] === 'object') {
s[i] = this.fixSchemaFormat(s[i]);
}
}
return s;
}
fixSchema(s) {
s = JSON.parse(JSON.stringify(s));
// Set applicable JSON Schema draft version if not already set
if (typeof s.$schema === 'undefined') {
s.$schema = "http://json-schema.org/draft-07/schema#";
}
// format => typehint (see above)
s = this.fixSchemaFormat(s);
return s;
}
async validateJson(json, schema) {
schema = this.fixSchema(schema);
schema.$async = true;
try {
await this.ajv.validate(schema, json);
/**
* Tries to determine the most suitable version from a well-known discovery document that software is compatible to.
*
* @static
* @param {array} wkVersions - A well-known discovery document compliant to the API specification.
* @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable.
*/
static findCompatible(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
if (!Array.isArray(wkVersions) || wkVersions.length === 0) {
return [];
} catch (e) {
if (Array.isArray(e.errors)) {
return e.errors.map(e => e.message);
}
else {
throw e;
}
}
}
validateJsonSchema(schema) {
schema = JSON.parse(JSON.stringify(schema));
schema = this.fixSchema(schema);
let result = this.ajv.compile(schema);
return result.errors || [];
}
// Pass the content of https://geojson.org/schema/GeoJSON.json
setGeoJsonSchema(schema) {
var gjv = new ajv();
this.geoJsonValidator = gjv.compile(schema);
}
// Expects API compatible output formats (see GET /output_formats).
setOutputFormats(outputFormats) {
this.outputFormats = {};
for (var key in outputFormats) {
this.outputFormats[key.toUpperCase()] = outputFormats[key];
}
}
/* istanbul ignore next */
async validateBandName(/*data*/) {
// Can't validate band name without knowing/loading the data.
// => To be overridden by end-user application.
return true;
}
/* istanbul ignore next */
async validateBoundingBox(/*data*/) {
// Nothing to validate, schema is (usually) delivered by processes.
return true;
}
/* istanbul ignore next */
async validateCallback(/*data*/) {
// This should be checked by process graph parsing automatically.
// Otherwise to be overridden by end-user application.
return true;
}
/* istanbul ignore next */
async validateCollectionId(/*data*/) {
// To be overridden by end-user application.
return true;
}
async validateEpsgCode(data) {
// Rough check for valid numbers as we don't want to maintain a full epsg code list in this repo.
// Fully validation to be implemented by end-user application by overriding this method.
if (data >= 2000) {
return true;
}
throw new ajv.ValidationError([{
message: "Invalid EPSG code specified."
}]);
}
// A very rough GeoJSON validation if no GeoJSON schema is available.
validateGeoJsonSimple(data) {
if (!Utils.isObject(data)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (not an object)."
}]);
}
else if (typeof data.type !== 'string') {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (no type property)."
}]);
}
switch(data.type) {
case "Point":
case "MultiPoint":
case "LineString":
case "MultiLineString":
case "Polygon":
case "MultiPolygon":
if (!Array.isArray(data.coordinates)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (Geometry has no valid coordinates member)."
}]);
let compatible = wkVersions.filter(c => {
if (typeof c.url === 'string' && Versions.validate(c.api_version)) {
let hasMinVer = Versions.validate(minVersion);
let hasMaxVer = Versions.validate(maxVersion);
if (hasMinVer && hasMaxVer) {
return Versions.compare(c.api_version, minVersion, ">=") && Versions.compare(c.api_version, maxVersion, "<=");
}
return true;
case "GeometryCollection":
if (!Array.isArray(data.geometries)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (GeometryCollection has no valid geometries member)."
}]);
else if (hasMinVer) {
return Versions.compare(c.api_version, minVersion, ">=");
}
return true;
case "Feature":
if (data.geometry !== null && !Utils.isObject(data.geometry)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (Feature has no valid geometry member)."
}]);
else if (hasMaxVer) {
return Versions.compare(c.api_version, maxVersion, "<=");
}
if (data.properties !== null && !Utils.isObject(data.properties)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (Feature has no valid properties member)."
}]);
}
return true;
case "FeatureCollection":
if (!Array.isArray(data.features)) {
throw new ajv.ValidationError([{
message: "Invalid GeoJSON specified (FeatureCollection has no valid features member)."
}]);
}
return true;
default:
throw new ajv.ValidationError([{
message: "Invalid GeoJSON type specified."
}]);
}
}
async validateGeoJson(data) {
if (this.geoJsonValidator !== null) {
if (!this.geoJsonValidator(data)) {
throw new ajv.ValidationError(this.geoJsonValidator.errors);
}
return true;
}
else {
return this.validateGeoJsonSimple(data);
}
}
/* istanbul ignore next */
async validateJobId(/*data*/) {
// To be overridden by end-user application
return true;
}
/* istanbul ignore next */
async validateKernel(/*data*/) {
// ToDo? / To be overridden by end-user application
return true;
}
async validateOutputFormat(data) {
if (Utils.isObject(this.outputFormats) && !(data.toUpperCase() in this.outputFormats)) {
throw new ajv.ValidationError([{
message: "Output format not supported."
}]);
}
return true;
}
/* istanbul ignore next */
async validateOutputFormatOptions(/*data*/) {
// This depends on the output format specified and can't be fully validated without knowning the chosen output format.
return true;
}
/* istanbul ignore next */
async validateProcessGraphId(/*data*/) {
// To be overridden by end-user application
return true;
}
/* istanbul ignore next */
async validateProcessGraphVariables(/*data*/) {
// Nothing to validate against...
return true;
}
async validateProjDefinition(data) {
// To be overridden by end-user application, just doing a very basic check here.
if (!data.toLowerCase().includes("+proj")) {
throw new ajv.ValidationError([{
message: "Invalid PROJ string specified (doesn't contain '+proj')."
}]);
}
return true;
}
/* istanbul ignore next */
async validateRasterCube(/*data*/) {
// This is usually a reference to a process result as we haven't specified any JSON encoding for raster cubes.
return true;
}
async validateTemporalInterval(/*data*/) {
// ToDo: Fully check against schema, most is already checked by JSON Schemas itself, but check for example that
// both can't be null at the same time or the first element is > the second element.
return true;
}
async validateTemporalIntervals(data) {
var invalid = data.filter(x => !this.validateTemporalInterval(x));
return invalid.length === 0;
}
/* istanbul ignore next */
async validateVectorCube(/*data*/) {
// This is usually a reference to a process result as we haven't specified any JSON encoding for raster cubes.
return true;
}
// Checks whether the valueSchema is compatible to the paramSchema.
// So would a value compatible with valueSchema be accepted by paramSchema?
// allowValueAsElements: If true, it checks whether the valueSchema would be allowed as part of an array or object. For example number could be allowed as part of an array of numbers.
static isSchemaCompatible(paramSchema, valueSchema, strict = false, allowValueAsElements = false) {
var paramSchemas = this._convertSchemaToArray(paramSchema);
var valueSchemas = this._convertSchemaToArray(valueSchema);
var compatible = paramSchemas.filter(ps => {
for(var i in valueSchemas) {
var vs = valueSchemas[i];
if (typeof ps.type !== 'string' || (!strict && typeof vs.type !== 'string')) { // "any" type is always compatible
else {
return true;
}
else if (ps.type === vs.type || (allowValueAsElements && (ps.type === 'array' || ps.type === 'object')) || (ps.type === 'number' && vs.type === 'integer') || (!strict && ps.type === 'integer' && vs.type === 'number')) {
if (ps.type === 'array' && Utils.isObject(ps.items) && Utils.isObject(vs.items)) {
if (allowValueAsElements && JsonSchemaValidator.isSchemaCompatible(ps.items, vs, strict)) {
return true;
}
else if (JsonSchemaValidator.isSchemaCompatible(ps.items, vs.items, strict)) {
return true;
}
}
else if (ps.type === 'object' && Utils.isObject(ps.properties) && Utils.isObject(vs.properties)) {
// ToDo: Check properties, required properties etc.
// If allowValueAsElements is true, all types are allowed to be part of the object.
return true;
}
else if (!strict && (typeof ps.format !== 'string' || typeof vs.format !== 'string')) {
return true;
}
else if (typeof ps.format !== 'string') { // types without format always accepts the same type with a format
return true;
}
else if (ps.format === vs.format) {
return true;
}
}
}
return false;
});
return compatible.length > 0;
}
static _convertSchemaToArray(schema) {
var schemas = [];
// ToDo: schema.not and schema.allOf is not supported - see also class constructor of ProcessSchema in processSchema.js of openeo-web-editor.
if (schema.oneOf || schema.anyOf) {
schemas = (schema.oneOf || schema.anyOf);
});
if (compatible.length === 0) {
return [];
}
else if (Array.isArray(schema.type)) {
schemas = schema.type.map(t => Object.assign({}, schema, {type: t}));
}
else {
schemas = [schema];
}
return schemas;
}
/**
* Returns the indices of provided JSON Schemas that the provided values matches against.
*
* Returns a single index if a single type is mathcing.
* Returns undefined if no valid type is found.
* Returns an array of indices if multiple types are found.
*
* @param {Array} types - Array of JSON schemas
* @param {*} value - A value
* @return {(string[]|string|undefined)} - Returns matching indices, see description.
*/
static async getTypeForValue(types, value) {
var validator = new JsonSchemaValidator();
var potentialTypes = [];
for(var i in types) {
var errors = await validator.validateJson(value, types[i]);
if (errors.length === 0) {
potentialTypes.push(String(i));
return compatible.sort((c1, c2) => {
let p1 = c1.production !== false;
let p2 = c2.production !== false;
if (!preferProduction || p1 === p2) {
return Versions.compare(c1.api_version, c2.api_version) * -1; // `* -1` to sort in descending order.
}
}
return potentialTypes.length > 1 ? potentialTypes : potentialTypes[0];
}
};
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
const ErrorList = __webpack_require__(6);
const ProcessGraphError = __webpack_require__(1);
const ProcessGraphNode = __webpack_require__(2);
const Utils = __webpack_require__(0);
const VARIABLE_TYPES = ['string', 'number', 'boolean', 'array', 'object'];
module.exports = class ProcessGraph {
constructor(jsonProcessGraph, processRegistry) {
this.json = jsonProcessGraph;
this.processRegistry = processRegistry;
this.nodes = {};
this.startNodes = {};
this.resultNode = null;
this.childrenProcessGraphs = [];
this.parentNode = null;
this.parentProcessId = null;
this.parentParameterName = null;
this.variables = {};
this.parsed = false;
this.validated = false;
this.errors = new ErrorList();
this.parameters = {};
}
toJSON() {
return this.json;
}
createNodeInstance(json, id, parent) {
return new ProcessGraphNode(json, id, parent);
}
createProcessGraphInstance(json) {
return new ProcessGraph(json, this.processRegistry);
}
setParent(parent, parameterName) {
if (parent instanceof ProcessGraphNode) {
this.parentNode = parent;
this.parentProcessId = parent.process_id;
}
else {
this.parentNode = null;
this.parentProcessId = parent;
}
this.parentParameterName = parameterName;
}
isValid() {
return this.validated && this.errors.count() === 0;
}
addError(error) {
this.errors.add(error);
}
parse() {
if (this.parsed) {
return;
}
for(let id in this.json) {
this.nodes[id] = this.createNodeInstance(this.json[id], id, this);
}
var makeError = (errorId) => {
if (this.parentProcessId) {
return new ProcessGraphError(
errorId + 'Callback',
{
process_id: this.parentProcessId,
node_id: this.parentNode ? this.parentNode.id : 'N/A'
}
);
else if (p1) {
return -1;
}
else {
return new ProcessGraphError(errorId);
return 1;
}
};
for(let id in this.nodes) {
var node = this.nodes[id];
if (node.isResultNode) {
if (this.resultNode !== null) {
throw makeError('MultipleResultNodes');
}
this.resultNode = node;
}
this.parseArguments(id, node);
}
if (!this.findStartNodes()) {
throw makeError('StartNodeMissing');
}
if (this.resultNode === null) {
throw makeError('ResultNodeMissing');
}
this.parsed = true;
}
async validate(throwOnErrors = true) {
if (this.validated) {
return null;
}
this.validated = true;
// Parse
try {
this.parse();
} catch (error) {
this.addError(error);
if (throwOnErrors) {
throw error;
}
}
// Validate
await this.validateNodes(this.getStartNodes(), throwOnErrors);
return this.errors;
}
async execute(parameters = null) {
await this.validate();
this.reset();
this.setParameters(parameters);
await this.executeNodes(this.getStartNodes());
return this.getResultNode();
}
async validateNodes(nodes, throwOnErrors, previousNode = null) {
if (nodes.length === 0) {
return;
}
var promises = nodes.map(async (node) => {
// Validate this node after all dependencies are available
if (!node.solveDependency(previousNode)) {
return;
}
// Get process and validate
try {
await this.validateNode(node);
} catch (e) {
if (e instanceof ErrorList) {
this.errors.merge(e);
if (throwOnErrors) {
throw e.first();
}
}
else {
this.addError(e);
if (throwOnErrors) {
throw e;
}
}
}
await this.validateNodes(node.getNextNodes(), throwOnErrors, node);
});
await Promise.all(promises);
}
async validateNode(node) {
var process = this.getProcess(node);
return await process.validate(node);
}
async executeNodes(nodes, previousNode = null) {
if (nodes.length === 0) {
return;
static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion);
if (versions.length > 0) {
return versions[0];
}
var promises = nodes.map(async (node) => {
// Execute this node after all dependencies are available
if (!node.solveDependency(previousNode)) {
return;
}
var result = await this.executeNode(node);
node.setResult(result);
// Execute next nodes in chain
await this.executeNodes(node.getNextNodes(), node);
});
return Promise.all(promises);
}
async executeNode(node) {
var process = this.getProcess(node);
return await process.execute(node);
}
parseArguments(nodeId, node, args) {
if (typeof args === 'undefined') {
args = node.arguments;
else {
return null;
}
for(var argumentName in args) {
var arg = args[argumentName];
var type = ProcessGraphNode.getType(arg);
switch(type) {
case 'result':
this.connectNodes(node, arg.from_node);
break;
case 'variable':
this.parseVariable(arg);
break;
case 'callback':
arg.callback = this.createProcessGraph(arg.callback, node, argumentName);
break;
case 'callback-argument':
this.parseCallbackArgument(node, arg.from_argument);
break;
case 'array':
case 'object':
this.parseArguments(nodeId, node, arg);
break;
}
}
}
parseCallbackArgument(node, name) {
var cbParams = this.getCallbackParameters();
if (!Utils.isObject(cbParams) || !cbParams.hasOwnProperty(name)) {
throw new ProcessGraphError('CallbackArgumentInvalid', {
argument: name,
node_id: node.id,
process_id: node.process_id
});
}
}
createProcessGraph(json, node, argumentName) {
var pg = this.createProcessGraphInstance(json);
pg.setParent(node, argumentName);
pg.parse();
this.childrenProcessGraphs.push(pg);
return pg;
}
parseVariable(variable) {
// Check whether the variable id is valid
if (typeof variable.variable_id !== 'string') {
throw new ProcessGraphError('VariableIdInvalid');
}
var obj = {};
// Check whether the data type is valid
if (typeof variable.type !== 'undefined' && !VARIABLE_TYPES.includes(variable.type)) {
throw new ProcessGraphError('VariableTypeInvalid', variable);
}
obj.type = typeof variable.type !== 'undefined' ? variable.type : 'string';
// Check whether the defult value has the correct data type
var defaultType = ProcessGraphNode.getType(variable.default);
if (defaultType !== 'undefined') {
if (defaultType !== obj.type) {
throw new ProcessGraphError('VariableDefaultValueTypeInvalid', variable);
}
else {
obj.value = variable.default;
}
}
}
setParameters(parameters) {
if (typeof parameters === 'object' && parameters !== null) {
this.parameters = parameters;
}
}
getParameter(name) {
return this.parameters[name];
}
setVariableValues(variables) {
for(var i in variables) {
this.setVariable(i, variables[i]);
}
}
setVariableValue(id, value) {
if (typeof this.variables[id] !== 'object') {
this.variables[id] = {};
}
this.variables[id].value = value;
}
getVariableValue(id) {
var variable = this.variables[id];
if (typeof variable !== 'object' || typeof variable.value === 'undefined') {
throw new ProcessGraphError('VariableValueMissing', {variable_id: id});
}
var type = ProcessGraphNode.getType(variable.value);
if (type !== variable.type) {
throw new ProcessGraphError('VariableValueTypeInvalid', {variable_id: id, type: variable.type});
}
return this.variables[id].value;
}
connectNodes(node, prevNodeId) {
var prevNode = this.nodes[prevNodeId];
if (typeof prevNode === 'undefined') {
throw new ProcessGraphError('ReferencedNodeMissing', {node_id: prevNodeId});
}
node.addPreviousNode(prevNode);
prevNode.addNextNode(node);
}
findStartNodes() {
var found = false;
for(var id in this.nodes) {
var node = this.nodes[id];
if (node.isStartNode()) {
this.startNodes[id] = node;
found = true;
}
}
return found;
}
reset() {
for(var id in this.nodes) {
this.nodes[id].reset();
}
this.childrenProcessGraphs.forEach(child => child.reset());
}
getResultNode() {
return this.resultNode;
}
getStartNodes() {
return Object.values(this.startNodes);
}
getStartNodeIds() {
return Object.keys(this.startNodes);
}
getNode(nodeId) {
return this.nodes[nodeId];
}
getNodeCount() {
return Utils.size(this.nodes);
}
getNodes() {
return this.nodes;
}
getErrors() {
return this.errors;
}
getProcess(node) {
var process = this.processRegistry.get(node.process_id);
if (process === null) {
throw new ProcessGraphError('ProcessUnsupported', {process: node.process_id});
}
return process;
}
getParentProcess() {
return this.processRegistry.get(this.parentProcessId);
}
getCallbackParameters() {
var process = this.getParentProcess();
if (!this.parentParameterName || !process) {
return {};
}
var schema = process.schema.parameters[this.parentParameterName].schema;
if (Utils.isObject(schema.parameters)) {
return schema.parameters;
}
// ToDo: If a process parameter supports multiple different callbacks, i.e. reduce with either an array of two separate values, this
// can't be separated accordingly and we just return all potential values. So it might happen that people get a successful validation
// but they used the wrong callback parameters.
// See issue https://github.com/Open-EO/openeo-js-commons/issues/6
var cbParams = {};
var choice = schema.anyOf || schema.oneOf || schema.allOf;
if (Array.isArray(choice)) {
for(let i in choice) {
var p = choice[i];
if (Utils.isObject(p.parameters)) {
Object.assign(cbParams, p.parameters);
}
}
}
return cbParams;
}
};
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = class ErrorList {
constructor() {
this.errors = [];
}
first() {
return this.errors[0] || null;
}
last() {
return this.errors[this.errors.length-1] || null;
}
merge(errorList) {
this.errors = this.errors.concat(errorList.getAll());
}
add(error) {
this.errors.push(error);
}
}
count() {
return this.errors.length;
}
module.exports = Versions;
toJSON() {
return this.errors.map(e => {
if (typeof e.toJSON === 'function') {
return e.toJSON();
}
else {
return {
code: 'InternalError',
message: e.message
};
}
});
}
getMessage() {
var msg = '';
for (var i in this.errors) {
msg += (parseInt(i, 10)+1) + ". " + this.errors[i].message + "\r\n";
}
return msg.trim();
}
getAll() {
return this.errors;
}
};
/***/ }),
/* 7 */
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
// Migrations
const MigrateCapabilities = __webpack_require__(8);
const MigrateCollections = __webpack_require__(10);
const MigrateProcesses = __webpack_require__(11);
// Process graphs
const BaseProcess = __webpack_require__(3);
const JsonSchemaValidator = __webpack_require__(4);
const ProcessGraph = __webpack_require__(5);
const ProcessGraphError = __webpack_require__(1);
const ProcessGraphNode = __webpack_require__(2);
const ProcessRegistry = __webpack_require__(13);
const MigrateCapabilities = __webpack_require__(3);
const MigrateCollections = __webpack_require__(5);
const MigrateProcesses = __webpack_require__(6);
// Others
const ErrorList = __webpack_require__(6);
const FeatureList = __webpack_require__(14);
const Versions = __webpack_require__(1);
const Utils = __webpack_require__(0);

@@ -1389,56 +272,78 @@

MigrateProcesses,
BaseProcess,
JsonSchemaValidator,
ProcessGraph,
ProcessGraphError,
ProcessGraphNode,
ProcessRegistry,
ErrorList,
FeatureList,
Utils
Versions,
Utils,
};
/***/ }),
/* 8 */
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
const Utils = __webpack_require__(0);
const Versions = __webpack_require__(1);
var MigrateCapabilities = {
const NO_VERSION = "0.0.0";
guessApiVersion(capabilities) {
if (typeof capabilities.api_version === 'string') {
return capabilities.api_version;
}
else if (typeof capabilities.version === 'string') {
return capabilities.version;
}
class MigrateCapabilities {
/**
* Tries to determine the API version from the capabilities object.
*
* Returns the version number, e.g. "0.4.2", "1.0.0" or "0.0.0" (if unknown).
*
* @param {object} capabilities
* @returns {string}
*/
static guessApiVersion(capabilities) {
// No object passed
if (!Utils.isObject(capabilities)) {
return NO_VERSION;
}
// Get exact info from version fields
if (Versions.validate(capabilities.api_version)) {
return capabilities.api_version;
}
else if (Versions.validate(capabilities.version)) {
return capabilities.version;
}
// Now we are really guessing
else if (Array.isArray(capabilities.endpoints) && capabilities.endpoints.filter(e => e.path === '/output_formats').length > 0) {
return "0.4";
}
else if (!capabilities.backend_version && !capabilities.title && !capabilities.description && !capabilities.links) {
return "0.3";
}
else { // Latest version
return "1.0";
}
},
else if (Array.isArray(capabilities.endpoints)) {
if (capabilities.endpoints.filter(e => e.path === '/file_formats' || e.path === '/conformance' || e.path === '/files').length > 0) {
return "1.0.0";
}
else if (capabilities.endpoints.filter(e => e.path === '/output_formats' || e.path === '/files/{user_id}').length > 0) {
return "0.4.2";
}
else if (!capabilities.backend_version && !capabilities.title && !capabilities.description && !capabilities.links) {
return "0.3.1";
}
}
// Can't determine version
return NO_VERSION;
}
// Always returns a copy of the input object
convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumber = true, title = "Unknown", backend_version = "Unknown") {
var capabilities = Object.assign({}, originalCapabilities);
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "Unknown") {
if (version === null) {
version = this.guessApiVersion(capabilities);
version = this.guessApiVersion(originalCapabilities);
}
// convert v0.3 capabilities to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// version => api_version
if (typeof capabilities.version !== 'undefined') {
delete capabilities.version;
}
// Return empty if version number is not available
if (version === NO_VERSION) {
return {};
}
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let capabilities = Utils.deepClone(originalCapabilities);
// Fill & Update version number
if (!updateVersionNumbers) {
capabilities.api_version = version;
}
else {
capabilities.api_version = "1.0.0";
}
// Convert billing plans

@@ -1453,11 +358,19 @@ if (Utils.isObject(capabilities.billing)) {

// Convert endpoints
capabilities.endpoints = this.convertEndpointsToLatestSpec(capabilities.endpoints, version);
capabilities.endpoints = this.convertEndpointsToLatestSpec(capabilities.endpoints, version, updateEndpointPaths);
// Fill STAC Version field
if (!updateVersionNumbers && Versions.compare(version, "0.4.x", "=")) {
capabilities.stac_version = "0.6.2";
}
else if (updateVersionNumbers || typeof capabilities.stac_version !== 'string') {
capabilities.stac_version = "0.9.0";
}
// Add missing fields with somewhat useful data
if (updateVersionNumber || typeof capabilities.api_version !== 'string') {
capabilities.api_version = "1.0.0";
}
if (typeof capabilities.backend_version !== 'string') {
capabilities.backend_version = backend_version;
}
if (typeof capabilities.id !== 'string') {
capabilities.id = id;
}
if (typeof capabilities.title !== 'string') {

@@ -1474,53 +387,68 @@ capabilities.title = title;

return capabilities;
},
}
// Always returns a copy of the input object
convertBillingToLatestSpec(originalBilling, version) {
var billing = Object.assign({}, originalBilling);
// convert v0.3 billing info to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// Add paid flag to billing plans
if (Array.isArray(billing.plans)) {
billing.plans = billing.plans.map(plan => {
if (typeof plan.paid !== 'boolean') {
plan.paid = true;
if (typeof plan.name === 'string' && plan.name.toLowerCase().includes('free')) {
plan.paid = false;
}
}
return plan;
});
}
static convertBillingToLatestSpec(originalBilling, 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 (typeof billing.currency !== 'string') {
billing.currency = null;
}
return billing;
},
}
// Always returns a copy of the input object
convertEndpointsToLatestSpec(originalEndpoints, version) {
var endpoints = [];
if (Array.isArray(originalEndpoints)) {
endpoints = originalEndpoints.slice(0);
static convertEndpointsToLatestSpec(originalEndpoints, version, updatePaths = false) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
// convert v0.3 service types to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// Nothing to do as nothing has changed.
if (!Array.isArray(originalEndpoints)) {
return [];
}
let endpoints = Utils.deepClone(originalEndpoints);
// convert v0.4 endpoints to v1.0
if (Versions.compare(version, "0.4.x", "=")) {
if (updatePaths) {
endpoints = endpoints.map(e => {
switch (e.path) {
case '/output_formats':
e.path = '/file_formats';
break;
case '/files/{user_id}':
e.path = '/files';
break;
case '/files/{user_id}/{path}':
e.path = '/files/{path}';
break;
}
return e;
});
}
else {
// Nothing to do as structure has not changed.
}
}
return endpoints;
},
}
// Alias for convertFileFormatsToLatestSpec
convertOutputFormatsToLatestSpec(originalFormats, version) {
static convertOutputFormatsToLatestSpec(originalFormats, version) {
return this.convertFileFormatsToLatestSpec(originalFormats, version);
},
}
// Always returns a copy of the input object
convertFileFormatsToLatestSpec(originalFormats, version) {
var formats = Object.assign({}, originalFormats);
if (Utils.compareVersion(version, "0.3.x") === 0 && Utils.isObject(formats.formats)) {
formats = formats.formats;
static convertFileFormatsToLatestSpec(originalFormats, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let formats = Utils.deepClone(originalFormats);
if (Utils.compareVersion(version, "0.4.x") <= 0 && Utils.isObject(formats)) {
if (Versions.compare(version, "0.4.x", "=") && Utils.isObject(formats)) {
formats = {

@@ -1539,20 +467,71 @@ output: formats

return formats;
},
}
// Always returns a copy of the input object
convertServiceTypesToLatestSpec(originalTypes, version) {
var types = Object.assign({}, originalTypes);
// Nothing to do as nothing has changed in 0.3 and 0.4.
if (Utils.compareVersion(version, "0.4.x") > 0) {
// Add future changes here.
static convertServiceTypesToLatestSpec(originalTypes, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let types = Utils.deepClone(originalTypes);
if (Versions.compare(version, "0.4.x", "=")) {
for(let t in types) {
if (!Utils.isObject(types[t])) {
types[t] = {};
continue;
}
// Remove attributes
delete types[t].attributes;
// Rename parameters to configuration
if (Utils.isObject(types[t].parameters)) {
types[t].configuration = types[t].parameters;
}
delete types[t].parameters;
// Rename variables to process_parameters
if (Array.isArray(types[t].variables)) {
types[t].process_parameters = types[t].variables.map(v => {
let param = {
name: v.variable_id,
description: typeof v.description === 'string' ? v.description : "",
schema: {
type: [
typeof v.type === 'string' ? v.type : "string",
"null"
]
}
};
if (typeof v.default !== 'undefined') {
param.default = v.default;
}
return param;
});
}
delete types[t].variables;
}
}
return types;
},
}
// Always returns a copy of the input object
convertUdfRuntimesToLatestSpec(originalRuntimes, version) {
var runtimes = Object.assign({}, originalRuntimes);
static convertUdfRuntimesToLatestSpec(originalRuntimes, 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);
// Nothing to do, was not supported in 0.3 and nothing changed in 0.4.
if (Utils.compareVersion(version, "0.4.x") > 0) {
// Add future changes here.
if (Versions.compare(version, "0.4.x", "=")) {
for(let r in runtimes) {
if (!Utils.isObject(runtimes[r])) {
delete runtimes[r];
continue;
}
// null is not allowed any longer, replace with empty string
if (runtimes[r].description === null) {
runtimes[r].description = "";
}
}
}

@@ -1562,3 +541,3 @@ return runtimes;

};
}

@@ -1568,3 +547,3 @@ module.exports = MigrateCapabilities;

/***/ }),
/* 9 */
/* 4 */
/***/ (function(module, exports, __webpack_require__) {

@@ -1687,67 +666,244 @@

/***/ }),
/* 10 */
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
const Utils = __webpack_require__(0);
const Versions = __webpack_require__(1);
var MigrateCollections = {
const extMap = {
"cube": "datacube",
"eo": "eo",
"label": "label",
"pc": "pointcloud",
"proj": "projection",
"sar": "sar",
"sat": "sat",
"sci": "scientific"
};
const fieldMap = {
// Item to core
'item:license': 'license',
'item:providers': 'providers',
// EO to core
'eo:instrument': 'instruments',
'eo:platform': 'platform',
'eo:constellation': 'constellation',
// EO to proj
'eo:epsg': 'proj:epsg',
// EO to sat
'eo:off_nadir': 'sat:off_nadir_angle',
'eo:azimuth': 'sat:azimuth_angle',
'eo:sun_azimuth': 'sat:sun_azimuth_angle',
'eo:sun_elevation': 'sat:sun_elevation_angle',
// Datetime Range to core
'dtr:start_datetime': 'start_datetime',
'dtr:end_datetime': 'end_datetime',
// Point Cloud
'pc:schema': 'pc:schemas',
// SAR rename
'sar:type': 'sar:product_type',
'sar:polarization': 'sar:polarizations',
// SAR to core
'sar:instrument': 'instruments',
'sar:platform': 'platform',
'sar:constellation': 'constellation',
// SAR to sat
'sar:off_nadir': 'sat:off_nadir_angle',
'sar:relative_orbit': 'sat:relative_orbit',
// The following four fields don't translate directly, see code below
'sar:pass_direction': 'sat:orbit_state',
// sar:resolution => sar:resolution_range, sar:resolution_azimuth
// sar:pixel_spacing => sar:pixel_spacing_range, sar:pixel_spacing_azimuth
// sar:looks => sar:looks_range, sar:looks_azimuth, sar:looks_equivalent_number (opt)
};
const moveToRoot = [
'cube:dimensions',
'sci:publications',
'sci:doi',
'sci:citation'
];
class MigrateCollections {
// Always returns a copy of the input collection object
convertCollectionToLatestSpec(originalCollection, version) {
if (!version || typeof version !== 'string') {
throw new Error("No version specified");
static convertCollectionToLatestSpec(originalCollection, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
if (Utils.compareVersion(version, "0.5.x") >= 0) {
throw "Migrating collections from API version 0.4.0 is not supported yet";
// Make sure we don't alter the original object
let collection = Utils.deepClone(originalCollection);
// If collection has no id => seems to be an invalid collection => abort
if (typeof collection.id !== 'string' || collection.id.length === 0) {
return {};
}
var collection = Object.assign({}, originalCollection);
if (!Object.keys(collection).length) {
return collection;
// Update stac_version
if (!Versions.validate(collection.stac_version) || Versions.compare(collection.stac_version, "0.9.0", "<")) {
collection.stac_version = "0.9.0";
}
// convert v0.3 processes to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// name => id
collection.id = collection.name;
delete collection.name;
// Add stac_version
collection.stac_version = '0.6.1';
// Rename provider => providers
if (Array.isArray(collection.provider)) {
collection.providers = collection.provider;
delete collection.provider;
// Add missing extent upfront. Makes the following code simpler as it works on the object.
if (!Utils.isObject(collection.extent)) {
collection.extent = {};
}
// convert v0.4 collections to latest version
if (Versions.compare(version, "0.4.x", "=")) {
// Restructure spatial extent
if (Array.isArray(collection.extent.spatial)) {
collection.extent.spatial = {
bbox: [
collection.extent.spatial
]
};
}
if (typeof collection.properties !== 'object') {
collection.properties = {};
// Restructure temporal extent
if (Array.isArray(collection.extent.temporal)) {
collection.extent.temporal = {
interval: [
collection.extent.temporal
]
};
}
// Migrate eo:bands
if (collection['eo:bands'] !== null && typeof collection['eo:bands'] === 'object' && !Array.isArray(collection['eo:bands'])) {
var bands = [];
for(let key in collection['eo:bands']) {
var band = Object.assign({}, collection['eo:bands'][key]);
band.name = key;
if (typeof band.resolution !== 'undefined' && typeof band.gsd === 'undefined') {
band.gsd = band.resolution;
delete band.resolution;
// move properties to other_properties
if (Utils.isObject(collection.properties)) {
if (!Utils.isObject(collection.other_properties)) {
collection.other_properties = {};
}
for(let key in collection.properties) {
collection.other_properties[key] = {
values: [
collection.properties[key]
]
};
}
}
delete collection.properties;
// now we can work on all properties and migrate to summaries
let props = Utils.isObject(collection.other_properties) ? collection.other_properties : {};
for(let key in props) {
let val = props[key];
if (Utils.isObject(val) && (Array.isArray(val.extent) || Array.isArray(val.values))) {
if (Array.isArray(val.extent)) {
props[key] = {
min: val.extent[0],
max: val.extent[1]
};
}
if (typeof band.wavelength !== 'undefined' && typeof band.center_wavelength === 'undefined') {
band.center_wavelength = band.wavelength;
delete band.wavelength;
else { // val.value is an array
let is2dArray = val.values.filter(v => !Array.isArray(v)).length === 0;
if (is2dArray) {
if (val.values.length < 2) {
props[key] = val.values[0];
}
else {
props[key] = val.values.reduce((a, b) => a.concat(b));
}
}
else {
props[key] = val.values;
}
}
bands.push(band);
}
collection['eo:bands'] = bands;
else {
// If not valid, move to top-level
if (typeof collection[key] === 'undefined') {
collection[key] = val;
}
delete props[key];
}
}
// Move all other properties into properties.
for (let key in collection) {
if (key.includes(':')) {
collection.properties[key] = collection[key];
delete collection[key];
delete collection.other_properties;
collection.summaries = Utils.isObject(collection.summaries) ? collection.summaries : {};
for(let key in props) {
let val = props[key];
if (key === 'sar:pass_direction') {
// Convert null to geostationary
val = val.map(v => v === null ? 'geostationary' : v);
}
// Convert arrays into separate fields as needed for some SAR fields
if ((key === 'sar:resolution' || key === 'sar:pixel_spacing' || key === 'sar:looks') && Array.isArray(val) && val.length >= 2) {
collection.summaries[key + '_range'] = val.slice(0,1);
collection.summaries[key + '_azimuth'] = val.slice(1,2);
if (val.length > 2) {
collection.summaries[key + '_equivalent_number'] = val.slice(2,3);
}
}
// Do the renaming of fields
else if (typeof fieldMap[key] === 'string') {
collection.summaries[fieldMap[key]] = val;
}
// Move invalid summaries to the top level
else if (moveToRoot.includes(key) && Array.isArray(val) && val.length === 1) {
collection[key] = val[0];
}
// Do the general conversion
else {
collection.summaries[key] = val;
}
}
}
// Add missing required fields
if (typeof collection.description !== 'string') {
collection.description = "";
}
if (!Utils.isObject(collection.extent.spatial)) {
collection.extent.spatial = {};
}
if (!Utils.isObject(collection.extent.temporal)) {
collection.extent.temporal = {};
}
if (typeof collection.license !== 'string') {
collection.license = "proprietary";
}
if (!Utils.isObject(collection.summaries)) {
collection.summaries = {};
}
if (!Utils.isObject(collection['cube:dimensions'])) {
collection['cube:dimensions'] = {};
}
// 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;
});
// Fix stac_extensions
var extensions = Array.isArray(collection.stac_extensions) ? collection.stac_extensions : [];
for(var key in collection) {
let ext = null;
let prefix = key.split(':', 1);
if (key === 'deprecated' || key === 'version') {
ext = 'version';
}
else if (typeof extMap[prefix] === 'string') {
ext = extMap[prefix];
}
if (ext !== null && !extensions.includes(ext)) {
extensions.push(ext);
}
}
extensions.sort();
collection.stac_extensions = extensions;
return collection;
}
};
}

@@ -1757,26 +913,20 @@ module.exports = MigrateCollections;

/***/ }),
/* 11 */
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
const Utils = __webpack_require__(0);
const Versions = __webpack_require__(1);
var MigrateProcesses = {
class MigrateProcesses {
// Always returns a copy of the input process object
convertProcessToLatestSpec(originalProcess, version) {
if (!version || typeof version !== 'string') {
throw new Error("No version specified");
static convertProcessToLatestSpec(originalProcess, 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
var process = Object.assign({}, originalProcess);
let process = Utils.deepClone(originalProcess);
let isVersion03 = Utils.compareVersion(version, "0.3.x") === 0;
// name => id
if (isVersion03) {
process.id = process.name;
delete process.name;
}
// If process has no id => seems to be an invalid process, abort
// If process has no id => seems to be an invalid process => abort
if (typeof process.id !== 'string' || process.id.length === 0) {

@@ -1786,2 +936,34 @@ return {};

// Convert the parameters from object to array
if (Versions.compare(version, "0.4.x", "=")) {
// Determine the parameter order
if (!Array.isArray(process.parameter_order) || process.parameter_order.length === 0) {
process.parameter_order = [];
for(let param in process.parameters) {
process.parameter_order.push(param);
}
}
// Upgrade parameters and convert from array to object
let params = [];
for(let name of process.parameter_order) {
// Add name
let obj = {name: name};
if (Utils.isObject(process.parameters[name])) {
Object.assign(obj, process.parameters[name]);
}
// Migrate from required to optional
if (!obj.required) {
obj.optional = true;
}
delete obj.required;
// Add to list of ordered params
params.push(obj);
}
delete process.parameter_order;
process.parameters = params;
}
// Set required field description if not a string

@@ -1792,52 +974,28 @@ if (typeof process.description !== 'string') {

// Parameters
if (Utils.isObject(process.parameters)) {
for(var key in process.parameters) {
process.parameters[key] = upgradeParamAndReturn(process.parameters[key], version);
// Update parameters
if (Array.isArray(process.parameters)) {
for(let i in process.parameters) {
let param = process.parameters[i];
if (!Utils.isObject(param)) {
continue;
}
// Set required field description if not a string
if (typeof param.description !== 'string') {
param.description = "";
}
// Upgrade parameter schema
process.parameters[i] = upgradeSchema(param, version);
}
}
else {
process.parameters = {};
process.parameters = [];
}
// Return value
process.returns = upgradeParamAndReturn(process.returns, version);
if (isVersion03) {
// exception object
if (Utils.isObject(process.exceptions)) {
for(let key in process.exceptions) {
var e = process.exceptions[key];
if (typeof e.message === 'undefined') {
process.exceptions[key] = Object.assign({}, e, {
message: e.description
});
}
}
}
// examples object
if (Utils.isObject(process.examples)) {
var examples = [];
for(let key in process.examples) {
var old = process.examples[key];
var example = {
title: old.summary || key,
description: old.description
};
if (old.process_graph) {
example.process_graph = old.process_graph;
}
examples.push(example);
}
process.examples = examples;
}
// Fill parameter order
if (typeof process.parameters === 'object' && !Array.isArray(process.parameter_order)) {
var parameter_order = Object.keys(process.parameters);
if (parameter_order.length > 1) {
process.parameter_order = parameter_order;
}
}
// Update return value
if (!Utils.isObject(process.returns)) {
process.returns = {};
}
process.returns = upgradeSchema(process.returns, version, false);

@@ -1847,37 +1005,20 @@ return process;

};
}
function upgradeParamAndReturn(obj, version) {
// Not an object => return minimum required fields
if (!Utils.isObject(obj)) {
return {
description: "",
schema: {}
};
function upgradeSchema(obj, version, isParam = true) {
var schema = {};
if (obj.schema && typeof obj.schema === 'object') { // array or object?
schema = obj.schema;
}
var param = Object.assign({}, obj);
// v0.3 => v0.4: mime_type => media_type
if (Utils.compareVersion(version, "0.3.x") === 0 && typeof param.mime_type !== 'undefined') {
param.media_type = param.mime_type;
delete param.mime_type;
}
// Set required fields if not valid yet
if (typeof param.description !== 'string') {
param.description = "";
}
if (typeof param.schema !== 'object' || !param.schema) {
param.schema = {};
}
if (Utils.compareVersion(version, "0.4.x") <= 0) {
if (Versions.compare(version, "0.4.x", "=")) {
// Remove anyOf/oneOf wrapper
for(var type in {anyOf: null, oneOf: null}) {
if (Array.isArray(param.schema[type])) {
if (typeof param.schema.default !== 'undefined') {
param.default = param.schema.default;
for(let type of ['anyOf', 'oneOf']) {
if (Array.isArray(schema[type])) {
// Parameters only: Move default value to parameter-level
if (isParam && typeof schema.default !== 'undefined') {
obj.default = schema.default;
}
param.schema = param.schema[type];
// Move array one level up, removing anyOf and oneOf
schema = schema[type];
break;

@@ -1887,37 +1028,69 @@ }

// Remove default value from schema, add on parameter-level instead
var moveMediaType = (Utils.compareVersion(version, "0.4.x") <= 0 && typeof param.media_type !== 'undefined');
var schemas = Array.isArray(param.schema) ? param.schema : [param.schema];
for(var i in schemas) {
if (typeof schemas[i].default !== 'undefined') {
param.default = schemas[i].default;
delete schemas[i].default;
let moveMediaType = (Versions.compare(version, "0.4.x") <= 0 && typeof obj.media_type !== 'undefined');
let schemas = Array.isArray(schema) ? schema : [schema];
for(let subSchema of schemas) {
// Rename format to subtype recursively
subSchema = renameFormat(subSchema);
// Parameters only: Move default value to parameter-level
if (isParam && typeof subSchema.default !== 'undefined') {
obj.default = subSchema.default;
delete subSchema.default;
}
// v0.3 => v0.4: mime_type => media_type
// Replace media_type field with contentMediaType from JSON Schemas
if (moveMediaType) {
schemas[i].contentMediaType = param.media_type;
subSchema.contentMediaType = obj.media_type;
}
renameFormat(schemas[i]);
}
// Remove the media type, has been moved to JSON Schema above.
// Remove the media type
if (moveMediaType) {
delete param.media_type;
delete obj.media_type;
}
}
return param;
obj.schema = schema;
return obj;
}
function renameFormat(schema) {
for(var i in schema) {
if (i === 'format') {
schema.subtype = schema.format;
if (!['date-time', 'time', 'date', 'uri'].includes(schema.format)) {
delete schema.format;
}
if (Utils.isObject(schema) && typeof schema.type !== 'undefined' && typeof schema.format === 'string') {
switch(schema.format) {
case 'url':
schema.format = 'uri';
break;
case 'proj-definition':
schema.deprecated = true;
break;
case 'callback':
schema.format = 'process-graph';
if (Utils.isObject(schema.parameters)) {
let params = [];
for(let name in schema.parameters) {
let paramSchema = schema.parameters[name];
let param = {
name: name,
description: typeof paramSchema.description === 'string' ? paramSchema.description : "",
schema: paramSchema
};
params.push(param);
}
schema.parameters = params;
}
break;
}
else if (schema[i] && typeof schema[i] === 'object') {
renameFormat(schema[i]);
schema.subtype = schema.format;
// Leave format for "well-known" formats defined in JSON Schema
if (!['date-time', 'time', 'date', 'uri'].includes(schema.format)) {
delete schema.format;
}
}
for(let i in schema) {
if (schema[i] && typeof schema[i] === 'object') {
schema[i] = renameFormat(schema[i]);
}
}
return schema;
}

@@ -1927,232 +1100,4 @@

/***/ }),
/* 12 */
/***/ (function(module, exports) {
if(typeof __WEBPACK_EXTERNAL_MODULE__12__ === 'undefined') {var e = new Error("Cannot find module 'ajv'"); e.code = 'MODULE_NOT_FOUND'; throw e;}
module.exports = __WEBPACK_EXTERNAL_MODULE__12__;
/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {
const BaseProcess = __webpack_require__(3);
const Utils = __webpack_require__(0);
module.exports = class ProcessRegistry {
constructor() {
// Keys added to this object must be lowercase!
this.processes = {};
}
addFromResponse(response) {
for(var i in response.processes) {
this.add(response.processes[i]);
}
}
add(process) {
this.processes[process.id] = new BaseProcess(process);
}
count() {
return Utils.size(this.processes);
}
get(id) {
if (typeof id === 'string') {
var pid = id.toLowerCase();
if (typeof this.processes[pid] !== 'undefined') {
return this.processes[pid];
}
}
return null;
}
getSchema(id) {
var p = this.get(id);
return p !== null ? p.schema : null;
}
getProcessSchemas() {
return Object.values(this.processes).map(impl => impl.schema);
}
};
/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {
const Utils = __webpack_require__(0);
var FeatureList = {
// Manual assignment of the endpoints above to individual features.
// A functionality is considered supported when ALL of the corresponding endpoints are supported.
features: {
'Basic functionality': [
'get /collections',
'get /collections/{}',
'get /processes',
'get /file_formats'
],
'Authenticate with HTTP Basic': [ // TODO: Remove later because this auth method should not be used
'get /credentials/basic',
// 'get /me' // not necessarily needed (just outputs metadata)
],
'Authenticate with OpenID Connect': [ // TODO: Remove later because the user doesn't care HOW the auth works
'get /credentials/oidc',
// 'get /me' // not necessarily needed (just outputs metadata)
],
'Batch processing': [
'get /jobs',
'post /jobs',
'get /jobs/{}',
// 'patch /jobs/{}', // not necessarily needed (can be achieved by deleting and re-creating)
'delete /jobs/{}',
'get /jobs/{}/logs',
'get /jobs/{}/results',
'post /jobs/{}/results',
// 'delete /jobs/{}/results' // not necessarily needed (can be deleted by deleting the entire job)
],
'Estimate processing costs': [
'get /jobs/{}/estimate'
],
'Preview processing results': [
'post /result'
],
'Secondary web services': [
'get /service_types',
'get /services',
'post /services',
'get /services/{}',
// 'patch /services/{}', // not necessarily needed (can be achieved by deleting and re-creating)
'delete /services/{}',
'get /services/{}/logs'
],
'File storage': [
'get /files/{}',
'get /files/{}/{}',
'put /files/{}/{}',
'delete /files/{}/{}'
],
'Stored process graphs': [
'get /process_graphs',
'post /process_graphs',
'get /process_graphs/{}',
// 'patch /process_graphs/{}', // not necessarily needed (can be achieved by deleting and re-creating)
'delete /process_graphs/{}'
],
'Validate process graphs': [
'post /validation',
],
'Notifications and monitoring': [
'get /subscription'
],
'User defined functions (UDF)': [
'get /udf_runtimes'
]
},
legacyFeatures: {
'post /result': {
'post /preview': ["0.3.*"]
},
'get /file_formats': {
'get /output_formats': ["0.3.*", "0.4.*"]
}
},
getListForVersion(version) {
var list = {};
for(var feature in this.features) {
list[feature] = [];
for(var i in this.features[feature]) {
var endpoint = this.findLegacyEndpoint(version, this.features[feature][i]);
list[feature].push(endpoint);
}
}
return list;
},
findLegacyEndpoint(version, endpoint, method = null) {
if (method !== null) {
endpoint = this.endpointToString(method, endpoint);
}
if (typeof this.legacyFeatures[endpoint] === 'object') {
var legacy = this.legacyFeatures[endpoint];
for(var legacyEndpoint in legacy) {
for(var i in legacy[legacyEndpoint]) {
var legacyVersion = legacy[legacyEndpoint][i];
if (Utils.compareVersion(version, legacyVersion) === 0) {
return legacyEndpoint;
}
}
}
}
return endpoint;
},
getFeatures() {
return Object.keys(this.features);
},
getFeatureCount() {
return Object.keys(this.features).length;
},
endpointsToStringList(endpoints) {
var list = [];
for(let i in endpoints) {
for(let j in endpoints[i].methods) {
list.push(this.endpointToString(endpoints[i].methods[j], endpoints[i].path));
}
}
return list;
},
endpointToString(method, path) {
// allow arbitrary parameter names => don't care about content in curly brackets
let request = method + ' ' + path.replace(/{[^}]+}/g, '{}');
return request.toLowerCase();
},
getReport(endpoints, version, convert = true) {
var supportedFeatureCount = 0;
var supportedEndpoints = convert ? this.endpointsToStringList(endpoints) : endpoints;
var status = this.getListForVersion(version);
// Assign each functionality a supported flag (0 = none, 1 = partially, 2 = fully)
Object.keys(status).forEach(key => {
let requiredEndpoints = status[key];
// Get a list of unsupported, but required endpoints
let unsupported = requiredEndpoints.filter(requiredEndpoint => !supportedEndpoints.includes(requiredEndpoint));
switch(unsupported.length) {
// No unsupported endpoints => fully supported
case 0:
status[key] = 2;
supportedFeatureCount++;
break;
// All endpoints are unsupported
case requiredEndpoints.length:
status[key] = 0;
break;
// Some endpoints are supported => partially supported
default:
status[key] = 1;
}
});
return {
count: supportedFeatureCount,
list: status
};
}
};
module.exports = FeatureList;
/***/ })
/******/ ]);
});

@@ -1,1 +0,1 @@

!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(function(){try{return require("ajv")}catch(e){}}());else if("function"==typeof define&&define.amd)define(["ajv"],t);else{var r="object"==typeof exports?t(function(){try{return require("ajv")}catch(e){}}()):t(e.ajv);for(var s in r)("object"==typeof exports?exports:e)[s]=r[s]}}(window,function(e){return function(e){var t={};function r(s){if(t[s])return t[s].exports;var a=t[s]={i:s,l:!1,exports:{}};return e[s].call(a.exports,a,a.exports,r),a.l=!0,a.exports}return r.m=e,r.c=t,r.d=function(e,t,s){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},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 s=Object.create(null);if(r.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)r.d(s,a,function(t){return e[t]}.bind(null,a));return s},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=7)}([function(e,t,r){const s=r(9);var a={compareVersion(e,t){try{return s(e,t)}catch(e){return null}},isObject:e=>"object"==typeof e&&e===Object(e)&&!Array.isArray(e),size:e=>"object"==typeof e&&null!==e?Array.isArray(e)?e.length:Object.keys(e).length:0,replacePlaceholders(e,t={}){if("string"==typeof e&&this.isObject(t))for(var r in t)e=e.replace("{"+r+"}",t[r]);return e}};e.exports=a},function(e,t,r){const s=r(0),a={MultipleResultNodes:"Multiple result nodes specified for process graph.",StartNodeMissing:"No start nodes found for process graph.",ResultNodeMissing:"No result node found for process graph.",MultipleResultNodesCallback:"Multiple result nodes specified for the callback in the process '{process_id}' (node: '{node_id}').",StartNodeMissingCallback:"No start nodes found for the callback in the process '{process_id}' (node: '{node_id}')'.",ResultNodeMissingCallback:"No result node found for the callback in the process '{process_id}' (node: '{node_id}').",ReferencedNodeMissing:"Referenced node '{node_id}' doesn't exist.",NodeIdInvalid:"Invalid node id specified in process graph.",NodeInvalid:"Process graph node '{node_id}' is not a valid object.",ProcessIdMissing:"Process graph node '{node_id}' doesn't contain a process id.",CallbackArgumentInvalid:"Invalid callback argument '{argument}' requested in the process '{process_id}' (node: '{node_id}').",ProcessUnsupported:"Process '{process}' is not supported.",ProcessArgumentUnsupported:"Process '{process}' does not support argument '{argument}'.",ProcessArgumentRequired:"Process '{process}' requires argument '{argument}'.",ProcessArgumentInvalid:"The argument '{argument}' in process '{process}' is invalid: {reason}",VariableValueMissing:"No value specified for process graph variable '{variable_id}'.",VariableDefaultValueTypeInvalid:"The default value specified for the process graph variable '{variable_id}' is not of type '{type}'.",VariableValueTypeInvalid:"The value specified for the process graph variable '{variable_id}' is not of type '{type}'.",VariableIdInvalid:"A specified variable ID is not valid.",VariableTypeInvalid:"The data type specified for the process graph variable '{variable_id}' is invalid. Must be one of: string, boolean, number, array or object."};e.exports=class extends Error{constructor(e,t={}){super(),this.variables=t,"string"==typeof a[e]?(this.code=e,this.message=s.replacePlaceholders(a[e],t)):(this.code=e.replace(/[^\w\d]+/g,""),this.message=e)}toJSON(){return{code:this.code,message:this.message}}}},function(e,t,r){const s=r(1),a=r(0);e.exports=class e{constructor(e,t,r){if("string"!=typeof t||0===t.length)throw new s("NodeIdInvalid");if(!a.isObject(e))throw new s("NodeInvalid",{node_id:t});if("string"!=typeof e.process_id)throw new s("ProcessIdMissing",{node_id:t});this.id=t,this.processGraph=r,this.process_id=e.process_id,this.arguments=a.isObject(e.arguments)?JSON.parse(JSON.stringify(e.arguments)):{},this.description=e.description||null,this.isResultNode=e.result||!1,this.expectsFrom=[],this.passesTo=[],this.result=null,this.resultsAvailableFrom=[]}getProcessGraph(){return this.processGraph}getArgumentNames(){return Object.keys(this.arguments)}hasArgument(e){return e in this.arguments}getArgumentType(t){return e.getType(this.arguments[t])}getRawArgument(e){return this.arguments[e]}getRawArgumentValue(t){var r=this.arguments[t];switch(e.getType(r)){case"result":return r.from_node;case"callback":return r.callback;case"callback-argument":return r.from_argument;default:return r}}getArgument(e,t){return void 0===this.arguments[e]?t:this.processArgument(this.arguments[e])}processArgument(t){switch(e.getType(t)){case"result":return this.processGraph.getNode(t.from_node).getResult();case"callback":return t.callback;case"callback-argument":return this.processGraph.getParameter(t.from_argument);case"variable":return this.processGraph.getVariableValue(t.variable_id);case"array":case"object":for(var r in t)t[r]=this.processArgument(t[r]);return t;default:return t}}static getType(e,t="null"){return"object"==typeof e?null===e?t:Array.isArray(e)?"array":e.hasOwnProperty("callback")?"callback":e.hasOwnProperty("variable_id")?"variable":e.hasOwnProperty("from_node")?"result":e.hasOwnProperty("from_argument")?"callback-argument":"object":typeof e}isStartNode(){return 0===this.expectsFrom.length}addPreviousNode(e){this.expectsFrom.push(e)}getPreviousNodes(){return this.expectsFrom}addNextNode(e){this.passesTo.push(e)}getNextNodes(){return this.passesTo}reset(){this.result=null,this.resultsAvailableFrom=[]}setDescription(e){this.description="string"==typeof e?e:null}setResult(e){this.result=e}getResult(){return this.result}solveDependency(e){return null!==e&&this.expectsFrom.includes(e)&&this.resultsAvailableFrom.push(e),this.expectsFrom.length===this.resultsAvailableFrom.length}}},function(e,t,r){const s=r(4),a=r(1),i=r(2),o=r(5);e.exports=class{constructor(e,t=null){this.schema=e,this.jsonSchema=null===t?new s:t}async validate(e){var t=e.getArgumentNames().filter(e=>void 0===this.schema.parameters[e]);if(t.length>0)throw new a("ProcessArgumentUnsupported",{process:this.schema.id,argument:t[0]});for(let t in this.schema.parameters){let r=this.schema.parameters[t],s=e.getRawArgument(t);if(await this.validateArgument(s,e,t,r))continue;let i=await this.jsonSchema.validateJson(s,r.schema);if(i.length>0)throw new a("ProcessArgumentInvalid",{process:this.schema.id,argument:t,reason:i.join("; ")})}}async validateArgument(e,t,r,n){let c=i.getType(e);if(e instanceof o)return await e.validate(!0),!0;switch(c){case"undefined":if(n.required)throw new a("ProcessArgumentRequired",{process:this.schema.id,argument:r});return!0;case"callback-argument":var l=t.getProcessGraph().getCallbackParameters();return s.isSchemaCompatible(n.schema,l[e.from_argument]);case"variable":var p={type:e.type||"string"};return s.isSchemaCompatible(n.schema,p);case"result":try{var d=t.getProcessGraph(),u=d.getNode(e.from_node).process_id,h=d.getProcess(u);return s.isSchemaCompatible(n.schema,h.schema.returns.schema)}catch(e){}break;case"array":case"object":return!0}return!1}async execute(){throw"execute not implemented yet"}test(){throw"test not implemented yet"}}},function(e,t,r){var s;try{s=r(12)}catch(e){}const a=r(0);e.exports=class e{constructor(){this.typeHints={"band-name":{type:"string",validate:"validateBandName"},"bounding-box":{type:"object",validate:"validateBoundingBox"},callback:{type:"object",validate:"validateCallback"},"collection-id":{type:"string",validate:"validateCollectionId"},"epsg-code":{type:"integer",validate:"validateEpsgCode"},geojson:{type:"object",validate:"validateGeoJson"},"job-id":{type:"string",validate:"validateJobId"},kernel:{type:"array",validate:"validateKernel"},"output-format":{type:"string",validate:"validateOutputFormat"},"output-format-options":{type:"object",validate:"validateOutputFormatOptions"},"process-graph-id":{type:"string",validate:"validateProcessGraphId"},"process-graph-variables":{type:"object",validate:"validateProcessGraphVariables"},"proj-definition":{type:"string",validate:"validateProjDefinition"},"raster-cube":{type:"object",validate:"validateRasterCube"},"temporal-interval":{type:"array",validate:"validateTemporalInterval"},"temporal-intervals":{type:"array",validate:"validateTemporalIntervals"},"vector-cube":{type:"object",validate:"validateVectorCube"}};var e={schemaId:"auto",format:"full",unknownFormats:Object.keys(this.typeHints)};if(!s)throw"ajv not installed";this.ajv=new s(e),this.ajv.addKeyword("parameters",{dependencies:["type","format"],metaSchema:{type:"object",additionalProperties:{type:"object"}},valid:!0,errors:!0}),this.ajv.addKeyword("typehint",{dependencies:["type"],validate:async(e,t,r)=>{if("object"==typeof this.typeHints[e]){var s=this.typeHints[e];if(s.type===r.type||Array.isArray(r.type)&&r.type.includes(s.type))return await this[s.validate](t)}return!1},async:!0,errors:!0}),this.outputFormats=null,this.geoJsonValidator=null}fixSchemaFormat(e){for(var t in e)"format"===t&&"string"==typeof e[t]&&Object.keys(this.typeHints).includes(e[t])&&(e.typehint=e[t]),e[t]&&"object"==typeof e[t]&&(e[t]=this.fixSchemaFormat(e[t]));return e}fixSchema(e){return void 0===(e=JSON.parse(JSON.stringify(e))).$schema&&(e.$schema="http://json-schema.org/draft-07/schema#"),e=this.fixSchemaFormat(e)}async validateJson(e,t){(t=this.fixSchema(t)).$async=!0;try{return await this.ajv.validate(t,e),[]}catch(e){if(Array.isArray(e.errors))return e.errors.map(e=>e.message);throw e}}validateJsonSchema(e){return e=JSON.parse(JSON.stringify(e)),e=this.fixSchema(e),this.ajv.compile(e).errors||[]}setGeoJsonSchema(e){var t=new s;this.geoJsonValidator=t.compile(e)}setOutputFormats(e){for(var t in this.outputFormats={},e)this.outputFormats[t.toUpperCase()]=e[t]}async validateBandName(){return!0}async validateBoundingBox(){return!0}async validateCallback(){return!0}async validateCollectionId(){return!0}async validateEpsgCode(e){if(e>=2e3)return!0;throw new s.ValidationError([{message:"Invalid EPSG code specified."}])}validateGeoJsonSimple(e){if(!a.isObject(e))throw new s.ValidationError([{message:"Invalid GeoJSON specified (not an object)."}]);if("string"!=typeof e.type)throw new s.ValidationError([{message:"Invalid GeoJSON specified (no type property)."}]);switch(e.type){case"Point":case"MultiPoint":case"LineString":case"MultiLineString":case"Polygon":case"MultiPolygon":if(!Array.isArray(e.coordinates))throw new s.ValidationError([{message:"Invalid GeoJSON specified (Geometry has no valid coordinates member)."}]);return!0;case"GeometryCollection":if(!Array.isArray(e.geometries))throw new s.ValidationError([{message:"Invalid GeoJSON specified (GeometryCollection has no valid geometries member)."}]);return!0;case"Feature":if(null!==e.geometry&&!a.isObject(e.geometry))throw new s.ValidationError([{message:"Invalid GeoJSON specified (Feature has no valid geometry member)."}]);if(null!==e.properties&&!a.isObject(e.properties))throw new s.ValidationError([{message:"Invalid GeoJSON specified (Feature has no valid properties member)."}]);return!0;case"FeatureCollection":if(!Array.isArray(e.features))throw new s.ValidationError([{message:"Invalid GeoJSON specified (FeatureCollection has no valid features member)."}]);return!0;default:throw new s.ValidationError([{message:"Invalid GeoJSON type specified."}])}}async validateGeoJson(e){if(null!==this.geoJsonValidator){if(!this.geoJsonValidator(e))throw new s.ValidationError(this.geoJsonValidator.errors);return!0}return this.validateGeoJsonSimple(e)}async validateJobId(){return!0}async validateKernel(){return!0}async validateOutputFormat(e){if(a.isObject(this.outputFormats)&&!(e.toUpperCase()in this.outputFormats))throw new s.ValidationError([{message:"Output format not supported."}]);return!0}async validateOutputFormatOptions(){return!0}async validateProcessGraphId(){return!0}async validateProcessGraphVariables(){return!0}async validateProjDefinition(e){if(!e.toLowerCase().includes("+proj"))throw new s.ValidationError([{message:"Invalid PROJ string specified (doesn't contain '+proj')."}]);return!0}async validateRasterCube(){return!0}async validateTemporalInterval(){return!0}async validateTemporalIntervals(e){return 0===e.filter(e=>!this.validateTemporalInterval(e)).length}async validateVectorCube(){return!0}static isSchemaCompatible(t,r,s=!1,i=!1){var o=this._convertSchemaToArray(t),n=this._convertSchemaToArray(r);return o.filter(t=>{for(var r in n){var o=n[r];if("string"!=typeof t.type||!s&&"string"!=typeof o.type)return!0;if(t.type===o.type||i&&("array"===t.type||"object"===t.type)||"number"===t.type&&"integer"===o.type||!s&&"integer"===t.type&&"number"===o.type)if("array"===t.type&&a.isObject(t.items)&&a.isObject(o.items)){if(i&&e.isSchemaCompatible(t.items,o,s))return!0;if(e.isSchemaCompatible(t.items,o.items,s))return!0}else{if("object"===t.type&&a.isObject(t.properties)&&a.isObject(o.properties))return!0;if(!(s||"string"==typeof t.format&&"string"==typeof o.format))return!0;if("string"!=typeof t.format)return!0;if(t.format===o.format)return!0}}return!1}).length>0}static _convertSchemaToArray(e){return e.oneOf||e.anyOf?e.oneOf||e.anyOf:Array.isArray(e.type)?e.type.map(t=>Object.assign({},e,{type:t})):[e]}static async getTypeForValue(t,r){var s=new e,a=[];for(var i in t){0===(await s.validateJson(r,t[i])).length&&a.push(String(i))}return a.length>1?a:a[0]}}},function(e,t,r){const s=r(6),a=r(1),i=r(2),o=r(0),n=["string","number","boolean","array","object"];e.exports=class e{constructor(e,t){this.json=e,this.processRegistry=t,this.nodes={},this.startNodes={},this.resultNode=null,this.childrenProcessGraphs=[],this.parentNode=null,this.parentProcessId=null,this.parentParameterName=null,this.variables={},this.parsed=!1,this.validated=!1,this.errors=new s,this.parameters={}}toJSON(){return this.json}createNodeInstance(e,t,r){return new i(e,t,r)}createProcessGraphInstance(t){return new e(t,this.processRegistry)}setParent(e,t){e instanceof i?(this.parentNode=e,this.parentProcessId=e.process_id):(this.parentNode=null,this.parentProcessId=e),this.parentParameterName=t}isValid(){return this.validated&&0===this.errors.count()}addError(e){this.errors.add(e)}parse(){if(!this.parsed){for(let e in this.json)this.nodes[e]=this.createNodeInstance(this.json[e],e,this);var e=e=>this.parentProcessId?new a(e+"Callback",{process_id:this.parentProcessId,node_id:this.parentNode?this.parentNode.id:"N/A"}):new a(e);for(let r in this.nodes){var t=this.nodes[r];if(t.isResultNode){if(null!==this.resultNode)throw e("MultipleResultNodes");this.resultNode=t}this.parseArguments(r,t)}if(!this.findStartNodes())throw e("StartNodeMissing");if(null===this.resultNode)throw e("ResultNodeMissing");this.parsed=!0}}async validate(e=!0){if(this.validated)return null;this.validated=!0;try{this.parse()}catch(t){if(this.addError(t),e)throw t}return await this.validateNodes(this.getStartNodes(),e),this.errors}async execute(e=null){return await this.validate(),this.reset(),this.setParameters(e),await this.executeNodes(this.getStartNodes()),this.getResultNode()}async validateNodes(e,t,r=null){if(0!==e.length){var a=e.map(async e=>{if(e.solveDependency(r)){try{await this.validateNode(e)}catch(e){if(e instanceof s){if(this.errors.merge(e),t)throw e.first()}else if(this.addError(e),t)throw e}await this.validateNodes(e.getNextNodes(),t,e)}});await Promise.all(a)}}async validateNode(e){var t=this.getProcess(e);return await t.validate(e)}async executeNodes(e,t=null){if(0!==e.length){var r=e.map(async e=>{if(e.solveDependency(t)){var r=await this.executeNode(e);e.setResult(r),await this.executeNodes(e.getNextNodes(),e)}});return Promise.all(r)}}async executeNode(e){var t=this.getProcess(e);return await t.execute(e)}parseArguments(e,t,r){for(var s in void 0===r&&(r=t.arguments),r){var a=r[s];switch(i.getType(a)){case"result":this.connectNodes(t,a.from_node);break;case"variable":this.parseVariable(a);break;case"callback":a.callback=this.createProcessGraph(a.callback,t,s);break;case"callback-argument":this.parseCallbackArgument(t,a.from_argument);break;case"array":case"object":this.parseArguments(e,t,a)}}}parseCallbackArgument(e,t){var r=this.getCallbackParameters();if(!o.isObject(r)||!r.hasOwnProperty(t))throw new a("CallbackArgumentInvalid",{argument:t,node_id:e.id,process_id:e.process_id})}createProcessGraph(e,t,r){var s=this.createProcessGraphInstance(e);return s.setParent(t,r),s.parse(),this.childrenProcessGraphs.push(s),s}parseVariable(e){if("string"!=typeof e.variable_id)throw new a("VariableIdInvalid");var t={};if(void 0!==e.type&&!n.includes(e.type))throw new a("VariableTypeInvalid",e);t.type=void 0!==e.type?e.type:"string";var r=i.getType(e.default);if("undefined"!==r){if(r!==t.type)throw new a("VariableDefaultValueTypeInvalid",e);t.value=e.default}}setParameters(e){"object"==typeof e&&null!==e&&(this.parameters=e)}getParameter(e){return this.parameters[e]}setVariableValues(e){for(var t in e)this.setVariable(t,e[t])}setVariableValue(e,t){"object"!=typeof this.variables[e]&&(this.variables[e]={}),this.variables[e].value=t}getVariableValue(e){var t=this.variables[e];if("object"!=typeof t||void 0===t.value)throw new a("VariableValueMissing",{variable_id:e});if(i.getType(t.value)!==t.type)throw new a("VariableValueTypeInvalid",{variable_id:e,type:t.type});return this.variables[e].value}connectNodes(e,t){var r=this.nodes[t];if(void 0===r)throw new a("ReferencedNodeMissing",{node_id:t});e.addPreviousNode(r),r.addNextNode(e)}findStartNodes(){var e=!1;for(var t in this.nodes){var r=this.nodes[t];r.isStartNode()&&(this.startNodes[t]=r,e=!0)}return e}reset(){for(var e in this.nodes)this.nodes[e].reset();this.childrenProcessGraphs.forEach(e=>e.reset())}getResultNode(){return this.resultNode}getStartNodes(){return Object.values(this.startNodes)}getStartNodeIds(){return Object.keys(this.startNodes)}getNode(e){return this.nodes[e]}getNodeCount(){return o.size(this.nodes)}getNodes(){return this.nodes}getErrors(){return this.errors}getProcess(e){var t=this.processRegistry.get(e.process_id);if(null===t)throw new a("ProcessUnsupported",{process:e.process_id});return t}getParentProcess(){return this.processRegistry.get(this.parentProcessId)}getCallbackParameters(){var e=this.getParentProcess();if(!this.parentParameterName||!e)return{};var t=e.schema.parameters[this.parentParameterName].schema;if(o.isObject(t.parameters))return t.parameters;var r={},s=t.anyOf||t.oneOf||t.allOf;if(Array.isArray(s))for(let e in s){var a=s[e];o.isObject(a.parameters)&&Object.assign(r,a.parameters)}return r}}},function(e,t){e.exports=class{constructor(){this.errors=[]}first(){return this.errors[0]||null}last(){return this.errors[this.errors.length-1]||null}merge(e){this.errors=this.errors.concat(e.getAll())}add(e){this.errors.push(e)}count(){return this.errors.length}toJSON(){return this.errors.map(e=>"function"==typeof e.toJSON?e.toJSON():{code:"InternalError",message:e.message})}getMessage(){var e="";for(var t in this.errors)e+=parseInt(t,10)+1+". "+this.errors[t].message+"\r\n";return e.trim()}getAll(){return this.errors}}},function(e,t,r){const s=r(8),a=r(10),i=r(11),o=r(3),n=r(4),c=r(5),l=r(1),p=r(2),d=r(13),u=r(6),h=r(14),f=r(0);e.exports={MigrateCapabilities:s,MigrateCollections:a,MigrateProcesses:i,BaseProcess:o,JsonSchemaValidator:n,ProcessGraph:c,ProcessGraphError:l,ProcessGraphNode:p,ProcessRegistry:d,ErrorList:u,FeatureList:h,Utils:f}},function(e,t,r){const s=r(0);var a={guessApiVersion:e=>"string"==typeof e.api_version?e.api_version:"string"==typeof e.version?e.version:Array.isArray(e.endpoints)&&e.endpoints.filter(e=>"/output_formats"===e.path).length>0?"0.4":e.backend_version||e.title||e.description||e.links?"1.0":"0.3",convertCapabilitiesToLatestSpec(e,t=null,r=!0,a="Unknown",i="Unknown"){var o=Object.assign({},e);return null===t&&(t=this.guessApiVersion(o)),0===s.compareVersion(t,"0.3.x")&&void 0!==o.version&&delete o.version,s.isObject(o.billing)?o.billing=this.convertBillingToLatestSpec(o.billing,t):delete o.billing,o.endpoints=this.convertEndpointsToLatestSpec(o.endpoints,t),(r||"string"!=typeof o.api_version)&&(o.api_version="1.0.0"),"string"!=typeof o.backend_version&&(o.backend_version=i),"string"!=typeof o.title&&(o.title=a),"string"!=typeof o.description&&(o.description=""),Array.isArray(o.links)||(o.links=[]),o},convertBillingToLatestSpec(e,t){var r=Object.assign({},e);return 0===s.compareVersion(t,"0.3.x")&&Array.isArray(r.plans)&&(r.plans=r.plans.map(e=>("boolean"!=typeof e.paid&&(e.paid=!0,"string"==typeof e.name&&e.name.toLowerCase().includes("free")&&(e.paid=!1)),e))),r},convertEndpointsToLatestSpec(e,t){var r=[];return Array.isArray(e)&&(r=e.slice(0)),s.compareVersion(t,"0.3.x"),r},convertOutputFormatsToLatestSpec(e,t){return this.convertFileFormatsToLatestSpec(e,t)},convertFileFormatsToLatestSpec(e,t){var r=Object.assign({},e);return 0===s.compareVersion(t,"0.3.x")&&s.isObject(r.formats)&&(r=r.formats),s.compareVersion(t,"0.4.x")<=0&&s.isObject(r)&&(r={output:r}),s.isObject(r.input)||(r.input={}),s.isObject(r.output)||(r.output={}),r},convertServiceTypesToLatestSpec(e,t){var r=Object.assign({},e);return s.compareVersion(t,"0.4.x"),r},convertUdfRuntimesToLatestSpec(e,t){var r=Object.assign({},e);return s.compareVersion(t,"0.4.x"),r}};e.exports=a},function(e,t,r){var s,a,i;a=[],void 0===(i="function"==typeof(s=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,s=e.replace(/^v/,"").replace(/\+.*$/,""),a=(r="-",-1===(t=s).indexOf(r)?t.length:t.indexOf(r)),i=s.substring(0,a).split(".");return i.push(s.substring(a+1)),i}function r(e){return isNaN(Number(e))?e:Number(e)}function s(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 a(e,a){[e,a].forEach(s);for(var i=t(e),o=t(a),n=0;n<Math.max(i.length-1,o.length-1);n++){var c=parseInt(i[n]||0,10),l=parseInt(o[n]||0,10);if(c>l)return 1;if(l>c)return-1}var p=i[i.length-1],d=o[o.length-1];if(p&&d){var u=p.split(".").map(r),h=d.split(".").map(r);for(n=0;n<Math.max(u.length,h.length);n++){if(void 0===u[n]||"string"==typeof h[n]&&"number"==typeof u[n])return-1;if(void 0===h[n]||"string"==typeof u[n]&&"number"==typeof h[n])return 1;if(u[n]>h[n])return 1;if(h[n]>u[n])return-1}}else if(p||d)return p?-1:1;return 0}var i=[">",">=","=","<","<="];return a.compare=function(e,t,r){switch(function(e){if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===i.indexOf(e))throw new TypeError("Invalid operator, expected one of "+i.join("|"))}(r),r){case">":return a(e,t)>0;case">=":return a(e,t)>=0;case"<":return a(e,t)<0;case"<=":return a(e,t)<=0;default:return 0===a(e,t)}},a})?s.apply(t,a):s)||(e.exports=i)},function(e,t,r){const s=r(0);var a={convertCollectionToLatestSpec(e,t){if(!t||"string"!=typeof t)throw new Error("No version specified");if(s.compareVersion(t,"0.5.x")>=0)throw"Migrating collections from API version 0.4.0 is not supported yet";var r=Object.assign({},e);if(!Object.keys(r).length)return r;if(0===s.compareVersion(t,"0.3.x")){if(r.id=r.name,delete r.name,r.stac_version="0.6.1",Array.isArray(r.provider)&&(r.providers=r.provider,delete r.provider),"object"!=typeof r.properties&&(r.properties={}),null!==r["eo:bands"]&&"object"==typeof r["eo:bands"]&&!Array.isArray(r["eo:bands"])){var a=[];for(let e in r["eo:bands"]){var i=Object.assign({},r["eo:bands"][e]);i.name=e,void 0!==i.resolution&&void 0===i.gsd&&(i.gsd=i.resolution,delete i.resolution),void 0!==i.wavelength&&void 0===i.center_wavelength&&(i.center_wavelength=i.wavelength,delete i.wavelength),a.push(i)}r["eo:bands"]=a}for(let e in r)e.includes(":")&&(r.properties[e]=r[e],delete r[e])}return r}};e.exports=a},function(e,t,r){const s=r(0);var a={convertProcessToLatestSpec(e,t){if(!t||"string"!=typeof t)throw new Error("No version specified");var r=Object.assign({},e);let a=0===s.compareVersion(t,"0.3.x");if(a&&(r.id=r.name,delete r.name),"string"!=typeof r.id||0===r.id.length)return{};if("string"!=typeof r.description&&(r.description=""),s.isObject(r.parameters))for(var o in r.parameters)r.parameters[o]=i(r.parameters[o],t);else r.parameters={};if(r.returns=i(r.returns,t),a){if(s.isObject(r.exceptions))for(let e in r.exceptions){var n=r.exceptions[e];void 0===n.message&&(r.exceptions[e]=Object.assign({},n,{message:n.description}))}if(s.isObject(r.examples)){var c=[];for(let e in r.examples){var l=r.examples[e],p={title:l.summary||e,description:l.description};l.process_graph&&(p.process_graph=l.process_graph),c.push(p)}r.examples=c}if("object"==typeof r.parameters&&!Array.isArray(r.parameter_order)){var d=Object.keys(r.parameters);d.length>1&&(r.parameter_order=d)}}return r}};function i(e,t){if(!s.isObject(e))return{description:"",schema:{}};var r=Object.assign({},e);if(0===s.compareVersion(t,"0.3.x")&&void 0!==r.mime_type&&(r.media_type=r.mime_type,delete r.mime_type),"string"!=typeof r.description&&(r.description=""),"object"==typeof r.schema&&r.schema||(r.schema={}),s.compareVersion(t,"0.4.x")<=0){for(var a in{anyOf:null,oneOf:null})if(Array.isArray(r.schema[a])){void 0!==r.schema.default&&(r.default=r.schema.default),r.schema=r.schema[a];break}var i=s.compareVersion(t,"0.4.x")<=0&&void 0!==r.media_type,n=Array.isArray(r.schema)?r.schema:[r.schema];for(var c in n)void 0!==n[c].default&&(r.default=n[c].default,delete n[c].default),i&&(n[c].contentMediaType=r.media_type),o(n[c]);i&&delete r.media_type}return r}function o(e){for(var t in e)"format"===t?(e.subtype=e.format,["date-time","time","date","uri"].includes(e.format)||delete e.format):e[t]&&"object"==typeof e[t]&&o(e[t])}e.exports=a},function(t,r){if(void 0===e){var s=new Error("Cannot find module 'ajv'");throw s.code="MODULE_NOT_FOUND",s}t.exports=e},function(e,t,r){const s=r(3),a=r(0);e.exports=class{constructor(){this.processes={}}addFromResponse(e){for(var t in e.processes)this.add(e.processes[t])}add(e){this.processes[e.id]=new s(e)}count(){return a.size(this.processes)}get(e){if("string"==typeof e){var t=e.toLowerCase();if(void 0!==this.processes[t])return this.processes[t]}return null}getSchema(e){var t=this.get(e);return null!==t?t.schema:null}getProcessSchemas(){return Object.values(this.processes).map(e=>e.schema)}}},function(e,t,r){const s=r(0);var a={features:{"Basic functionality":["get /collections","get /collections/{}","get /processes","get /file_formats"],"Authenticate with HTTP Basic":["get /credentials/basic"],"Authenticate with OpenID Connect":["get /credentials/oidc"],"Batch processing":["get /jobs","post /jobs","get /jobs/{}","delete /jobs/{}","get /jobs/{}/logs","get /jobs/{}/results","post /jobs/{}/results"],"Estimate processing costs":["get /jobs/{}/estimate"],"Preview processing results":["post /result"],"Secondary web services":["get /service_types","get /services","post /services","get /services/{}","delete /services/{}","get /services/{}/logs"],"File storage":["get /files/{}","get /files/{}/{}","put /files/{}/{}","delete /files/{}/{}"],"Stored process graphs":["get /process_graphs","post /process_graphs","get /process_graphs/{}","delete /process_graphs/{}"],"Validate process graphs":["post /validation"],"Notifications and monitoring":["get /subscription"],"User defined functions (UDF)":["get /udf_runtimes"]},legacyFeatures:{"post /result":{"post /preview":["0.3.*"]},"get /file_formats":{"get /output_formats":["0.3.*","0.4.*"]}},getListForVersion(e){var t={};for(var r in this.features)for(var s in t[r]=[],this.features[r]){var a=this.findLegacyEndpoint(e,this.features[r][s]);t[r].push(a)}return t},findLegacyEndpoint(e,t,r=null){if(null!==r&&(t=this.endpointToString(r,t)),"object"==typeof this.legacyFeatures[t]){var a=this.legacyFeatures[t];for(var i in a)for(var o in a[i]){var n=a[i][o];if(0===s.compareVersion(e,n))return i}}return t},getFeatures(){return Object.keys(this.features)},getFeatureCount(){return Object.keys(this.features).length},endpointsToStringList(e){var t=[];for(let r in e)for(let s in e[r].methods)t.push(this.endpointToString(e[r].methods[s],e[r].path));return t},endpointToString:(e,t)=>(e+" "+t.replace(/{[^}]+}/g,"{}")).toLowerCase(),getReport(e,t,r=!0){var s=0,a=r?this.endpointsToStringList(e):e,i=this.getListForVersion(t);return Object.keys(i).forEach(e=>{let t=i[e];switch(t.filter(e=>!a.includes(e)).length){case 0:i[e]=2,s++;break;case t.length:i[e]=0;break;default:i[e]=1}}),{count:s,list:i}}};e.exports=a}])});
!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){e.exports=class{static isObject(e){return"object"==typeof e&&e===Object(e)&&!Array.isArray(e)}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}}},function(e,t,r){const i=r(4),n=/^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;class a{static compare(e,t,r=null){return null!==r?i.compare(e,t,r):i(e,t)}static validate(e){return"string"==typeof e&&n.test(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&&a.validate(e.api_version)){let t=a.validate(r),n=a.validate(i);return t&&n?a.compare(e.api_version,r,">=")&&a.compare(e.api_version,i,"<="):t?a.compare(e.api_version,r,">="):!n||a.compare(e.api_version,i,"<=")}return!1});return 0===n.length?[]:n.sort((e,r)=>{let i=!1!==e.production,n=!1!==r.production;return t&&i!==n?i?-1:1:-1*a.compare(e.api_version,r.api_version)})}static findLatest(e,t=!0,r=null,i=null){let n=a.findCompatible(e,t,r,i);return n.length>0?n[0]:null}}e.exports=a},function(e,t,r){const i=r(3),n=r(5),a=r(6),s=r(1),o=r(0);e.exports={MigrateCapabilities:i,MigrateCollections:n,MigrateProcesses:a,Versions:s,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,a=!0,s="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,a),!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"),"string"!=typeof l.backend_version&&(l.backend_version=p),"string"!=typeof l.id&&(l.id=s),"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 a=i.deepClone(e);return n.compare(t,"0.4.x","=")&&r&&(a=a.map(e=>{switch(e.path){case"/output_formats":e.path="/file_formats";break;case"/files/{user_id}":e.path="/files";break;case"/files/{user_id}/{path}":e.path="/files/{path}"}return e})),a}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=i.deepClone(e);return 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=i.deepClone(e);if(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,a;n=[],void 0===(a="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)),a=i.substring(0,n).split(".");return a.push(i.substring(n+1)),a}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 a=t(e),s=t(n),o=0;o<Math.max(a.length-1,s.length-1);o++){var p=parseInt(a[o]||0,10),l=parseInt(s[o]||0,10);if(p>l)return 1;if(l>p)return-1}var c=a[a.length-1],u=s[s.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 a=[">",">=","=","<","<="];return n.compare=function(e,t,r){switch(function(e){if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===a.indexOf(e))throw new TypeError("Invalid operator, expected one of "+a.join("|"))}(r),r){case">":return n(e,t)>0;case">=":return n(e,t)>=0;case"<":return n(e,t)<0;case"<=":return n(e,t)<=0;default:return 0===n(e,t)}},n})?i.apply(t,n):i)||(e.exports=a)},function(e,t,r){const i=r(0),n=r(1),a={cube:"datacube",eo:"eo",label:"label",pc:"pointcloud",proj:"projection",sar:"sar",sat:"sat",sci:"scientific"},s={"item:license":"license","item:providers":"providers","eo:instrument":"instruments","eo:platform":"platform","eo:constellation":"constellation","eo:epsg":"proj:epsg","eo:off_nadir":"sat:off_nadir_angle","eo:azimuth":"sat:azimuth_angle","eo:sun_azimuth":"sat:sun_azimuth_angle","eo:sun_elevation":"sat:sun_elevation_angle","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 s[t]?r.summaries[s[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 a[t]&&(e=a[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 a(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 a=n.compare(t,"0.4.x")<=0&&void 0!==e.media_type,o=Array.isArray(i)?i:[i];for(let t of o)t=s(t),r&&void 0!==t.default&&(e.default=t.default,delete t.default),a&&(t.contentMediaType=e.media_type);a&&delete e.media_type}return e.schema=i,e}function s(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]=s(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]=a(n,t))}else r.parameters=[];return i.isObject(r.returns)||(r.returns={}),r.returns=a(r.returns,t,!1),r}}}])}));
{
"name": "@openeo/js-commons",
"version": "0.5.0-alpha.1",
"version": "1.0.0-rc.1",
"author": "openEO Consortium",

@@ -25,5 +25,2 @@ "contributors": [

],
"peerDependencies": {
"ajv": "^6.10.0"
},
"devDependencies": {

@@ -30,0 +27,0 @@ "@babel/core": "^7.0.0",

@@ -6,6 +6,6 @@ # openeo-js-commons

This library's version is **0.5.0-alpha.1** and supports **openEO API version 1.0.x**. Legacy versions are available as releases.
This library's version is **1.0.0-rc.1** and supports **openEO API version 1.0.x**. Legacy versions are available as releases.
## Features
- Converting responses to the latest API version is supported for:
- Converting responses from API version 0.4 to the latest API version is supported for:
- Capabilities

@@ -16,9 +16,10 @@ - Collections

- Service Types
- UDF Runtimes
- Back-end feature detection
- Process graph handling:
- Parsing a process graph
- Validation based on the JSON Schemas
- Framework to implement process graph execution
- JSON Schema validation for Process parameters and return values
- Validate, compare and prioritize version numbers (e.g. for well-known discovery)
**Note:**
- Process graph parsing has been moved to [openeo-js-processgraphs](https://github.com/Open-EO/openeo-js-processgraphs).
- Support for migrating from API 0.3 to the latest API version has been dropped. Use the library in version 0.4 instead.
## Usage

@@ -28,3 +29,3 @@

You can then require the parts of the library you want to use. For example: `const { FeatureList } = require('@openeo/js-commons');`
You can then require the parts of the library you want to use. For example: `const { MigrateProcesses } = require('@openeo/js-commons');`

@@ -34,11 +35,6 @@ In a web environment you can include the library as follows:

```html
<script src="https://cdn.jsdelivr.net/npm/@openeo/js-commons@0.4/dist/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@openeo/js-commons@1.0.0-rc.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 -->
This library has a peer dependency to `ajv`, so if you'd like to use process graph validation or execution you need to include `ajv` (v6.10) in your package.json or include it in your web page:
```html
<script src="https://cdn.jsdelivr.net/npm/ajv@6.10/lib/ajv.min.js"></script>
```
More information can be found in the [**JS commons documentation**](https://open-eo.github.io/openeo-js-commons/0.5.0-alpha.1/).
More information can be found in the [**JS commons documentation**](https://open-eo.github.io/openeo-js-commons/1.0.0-rc.1/).

@@ -5,14 +5,4 @@ // Migrations

const MigrateProcesses = require('./migrate/processes');
// Process graphs
const BaseProcess = require('./processgraph/process');
const JsonSchemaValidator = require('./processgraph/jsonschema');
const ProcessGraph = require('./processgraph/processgraph');
const ProcessGraphError = require('./processgraph/error');
const ProcessGraphNode = require('./processgraph/node');
const ProcessRegistry = require('./processgraph/registry');
// Others
const ErrorList = require('./errorlist');
const FeatureList = require('./featurelist');
const Versions = require('./versions');
const Utils = require('./utils');

@@ -24,13 +14,4 @@

MigrateProcesses,
BaseProcess,
JsonSchemaValidator,
ProcessGraph,
ProcessGraphError,
ProcessGraphNode,
ProcessRegistry,
ErrorList,
FeatureList,
Utils
Versions,
Utils,
};
const Utils = require('../utils.js');
const Versions = require('../versions.js');
var MigrateCapabilities = {
const NO_VERSION = "0.0.0";
guessApiVersion(capabilities) {
if (typeof capabilities.api_version === 'string') {
return capabilities.api_version;
}
else if (typeof capabilities.version === 'string') {
return capabilities.version;
}
class MigrateCapabilities {
/**
* Tries to determine the API version from the capabilities object.
*
* Returns the version number, e.g. "0.4.2", "1.0.0" or "0.0.0" (if unknown).
*
* @param {object} capabilities
* @returns {string}
*/
static guessApiVersion(capabilities) {
// No object passed
if (!Utils.isObject(capabilities)) {
return NO_VERSION;
}
// Get exact info from version fields
if (Versions.validate(capabilities.api_version)) {
return capabilities.api_version;
}
else if (Versions.validate(capabilities.version)) {
return capabilities.version;
}
// Now we are really guessing
else if (Array.isArray(capabilities.endpoints) && capabilities.endpoints.filter(e => e.path === '/output_formats').length > 0) {
return "0.4";
}
else if (!capabilities.backend_version && !capabilities.title && !capabilities.description && !capabilities.links) {
return "0.3";
}
else { // Latest version
return "1.0";
}
},
else if (Array.isArray(capabilities.endpoints)) {
if (capabilities.endpoints.filter(e => e.path === '/file_formats' || e.path === '/conformance' || e.path === '/files').length > 0) {
return "1.0.0";
}
else if (capabilities.endpoints.filter(e => e.path === '/output_formats' || e.path === '/files/{user_id}').length > 0) {
return "0.4.2";
}
else if (!capabilities.backend_version && !capabilities.title && !capabilities.description && !capabilities.links) {
return "0.3.1";
}
}
// Can't determine version
return NO_VERSION;
}
// Always returns a copy of the input object
convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumber = true, title = "Unknown", backend_version = "Unknown") {
var capabilities = Object.assign({}, originalCapabilities);
static convertCapabilitiesToLatestSpec(originalCapabilities, version = null, updateVersionNumbers = true, updateEndpointPaths = true, id = "unknown", title = "Unknown", backend_version = "Unknown") {
if (version === null) {
version = this.guessApiVersion(capabilities);
version = this.guessApiVersion(originalCapabilities);
}
// convert v0.3 capabilities to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// version => api_version
if (typeof capabilities.version !== 'undefined') {
delete capabilities.version;
}
// Return empty if version number is not available
if (version === NO_VERSION) {
return {};
}
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let capabilities = Utils.deepClone(originalCapabilities);
// Fill & Update version number
if (!updateVersionNumbers) {
capabilities.api_version = version;
}
else {
capabilities.api_version = "1.0.0";
}
// Convert billing plans

@@ -47,11 +78,19 @@ if (Utils.isObject(capabilities.billing)) {

// Convert endpoints
capabilities.endpoints = this.convertEndpointsToLatestSpec(capabilities.endpoints, version);
capabilities.endpoints = this.convertEndpointsToLatestSpec(capabilities.endpoints, version, updateEndpointPaths);
// Fill STAC Version field
if (!updateVersionNumbers && Versions.compare(version, "0.4.x", "=")) {
capabilities.stac_version = "0.6.2";
}
else if (updateVersionNumbers || typeof capabilities.stac_version !== 'string') {
capabilities.stac_version = "0.9.0";
}
// Add missing fields with somewhat useful data
if (updateVersionNumber || typeof capabilities.api_version !== 'string') {
capabilities.api_version = "1.0.0";
}
if (typeof capabilities.backend_version !== 'string') {
capabilities.backend_version = backend_version;
}
if (typeof capabilities.id !== 'string') {
capabilities.id = id;
}
if (typeof capabilities.title !== 'string') {

@@ -68,53 +107,68 @@ capabilities.title = title;

return capabilities;
},
}
// Always returns a copy of the input object
convertBillingToLatestSpec(originalBilling, version) {
var billing = Object.assign({}, originalBilling);
// convert v0.3 billing info to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// Add paid flag to billing plans
if (Array.isArray(billing.plans)) {
billing.plans = billing.plans.map(plan => {
if (typeof plan.paid !== 'boolean') {
plan.paid = true;
if (typeof plan.name === 'string' && plan.name.toLowerCase().includes('free')) {
plan.paid = false;
}
}
return plan;
});
}
static convertBillingToLatestSpec(originalBilling, 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 (typeof billing.currency !== 'string') {
billing.currency = null;
}
return billing;
},
}
// Always returns a copy of the input object
convertEndpointsToLatestSpec(originalEndpoints, version) {
var endpoints = [];
if (Array.isArray(originalEndpoints)) {
endpoints = originalEndpoints.slice(0);
static convertEndpointsToLatestSpec(originalEndpoints, version, updatePaths = false) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
// convert v0.3 service types to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// Nothing to do as nothing has changed.
if (!Array.isArray(originalEndpoints)) {
return [];
}
let endpoints = Utils.deepClone(originalEndpoints);
// convert v0.4 endpoints to v1.0
if (Versions.compare(version, "0.4.x", "=")) {
if (updatePaths) {
endpoints = endpoints.map(e => {
switch (e.path) {
case '/output_formats':
e.path = '/file_formats';
break;
case '/files/{user_id}':
e.path = '/files';
break;
case '/files/{user_id}/{path}':
e.path = '/files/{path}';
break;
}
return e;
});
}
else {
// Nothing to do as structure has not changed.
}
}
return endpoints;
},
}
// Alias for convertFileFormatsToLatestSpec
convertOutputFormatsToLatestSpec(originalFormats, version) {
static convertOutputFormatsToLatestSpec(originalFormats, version) {
return this.convertFileFormatsToLatestSpec(originalFormats, version);
},
}
// Always returns a copy of the input object
convertFileFormatsToLatestSpec(originalFormats, version) {
var formats = Object.assign({}, originalFormats);
if (Utils.compareVersion(version, "0.3.x") === 0 && Utils.isObject(formats.formats)) {
formats = formats.formats;
static convertFileFormatsToLatestSpec(originalFormats, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let formats = Utils.deepClone(originalFormats);
if (Utils.compareVersion(version, "0.4.x") <= 0 && Utils.isObject(formats)) {
if (Versions.compare(version, "0.4.x", "=") && Utils.isObject(formats)) {
formats = {

@@ -133,20 +187,71 @@ output: formats

return formats;
},
}
// Always returns a copy of the input object
convertServiceTypesToLatestSpec(originalTypes, version) {
var types = Object.assign({}, originalTypes);
// Nothing to do as nothing has changed in 0.3 and 0.4.
if (Utils.compareVersion(version, "0.4.x") > 0) {
// Add future changes here.
static convertServiceTypesToLatestSpec(originalTypes, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
let types = Utils.deepClone(originalTypes);
if (Versions.compare(version, "0.4.x", "=")) {
for(let t in types) {
if (!Utils.isObject(types[t])) {
types[t] = {};
continue;
}
// Remove attributes
delete types[t].attributes;
// Rename parameters to configuration
if (Utils.isObject(types[t].parameters)) {
types[t].configuration = types[t].parameters;
}
delete types[t].parameters;
// Rename variables to process_parameters
if (Array.isArray(types[t].variables)) {
types[t].process_parameters = types[t].variables.map(v => {
let param = {
name: v.variable_id,
description: typeof v.description === 'string' ? v.description : "",
schema: {
type: [
typeof v.type === 'string' ? v.type : "string",
"null"
]
}
};
if (typeof v.default !== 'undefined') {
param.default = v.default;
}
return param;
});
}
delete types[t].variables;
}
}
return types;
},
}
// Always returns a copy of the input object
convertUdfRuntimesToLatestSpec(originalRuntimes, version) {
var runtimes = Object.assign({}, originalRuntimes);
static convertUdfRuntimesToLatestSpec(originalRuntimes, 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);
// Nothing to do, was not supported in 0.3 and nothing changed in 0.4.
if (Utils.compareVersion(version, "0.4.x") > 0) {
// Add future changes here.
if (Versions.compare(version, "0.4.x", "=")) {
for(let r in runtimes) {
if (!Utils.isObject(runtimes[r])) {
delete runtimes[r];
continue;
}
// null is not allowed any longer, replace with empty string
if (runtimes[r].description === null) {
runtimes[r].description = "";
}
}
}

@@ -156,4 +261,4 @@ return runtimes;

};
}
module.exports = MigrateCapabilities;
const Utils = require('../utils.js');
const Versions = require('../versions.js');
var MigrateCollections = {
const extMap = {
"cube": "datacube",
"eo": "eo",
"label": "label",
"pc": "pointcloud",
"proj": "projection",
"sar": "sar",
"sat": "sat",
"sci": "scientific"
};
const fieldMap = {
// Item to core
'item:license': 'license',
'item:providers': 'providers',
// EO to core
'eo:instrument': 'instruments',
'eo:platform': 'platform',
'eo:constellation': 'constellation',
// EO to proj
'eo:epsg': 'proj:epsg',
// EO to sat
'eo:off_nadir': 'sat:off_nadir_angle',
'eo:azimuth': 'sat:azimuth_angle',
'eo:sun_azimuth': 'sat:sun_azimuth_angle',
'eo:sun_elevation': 'sat:sun_elevation_angle',
// Datetime Range to core
'dtr:start_datetime': 'start_datetime',
'dtr:end_datetime': 'end_datetime',
// Point Cloud
'pc:schema': 'pc:schemas',
// SAR rename
'sar:type': 'sar:product_type',
'sar:polarization': 'sar:polarizations',
// SAR to core
'sar:instrument': 'instruments',
'sar:platform': 'platform',
'sar:constellation': 'constellation',
// SAR to sat
'sar:off_nadir': 'sat:off_nadir_angle',
'sar:relative_orbit': 'sat:relative_orbit',
// The following four fields don't translate directly, see code below
'sar:pass_direction': 'sat:orbit_state',
// sar:resolution => sar:resolution_range, sar:resolution_azimuth
// sar:pixel_spacing => sar:pixel_spacing_range, sar:pixel_spacing_azimuth
// sar:looks => sar:looks_range, sar:looks_azimuth, sar:looks_equivalent_number (opt)
};
const moveToRoot = [
'cube:dimensions',
'sci:publications',
'sci:doi',
'sci:citation'
];
class MigrateCollections {
// Always returns a copy of the input collection object
convertCollectionToLatestSpec(originalCollection, version) {
if (!version || typeof version !== 'string') {
throw new Error("No version specified");
static convertCollectionToLatestSpec(originalCollection, version) {
if (Versions.compare(version, "0.3.x", "<=")) {
throw "Migrating from API version 0.3.0 and older is not supported.";
}
if (Utils.compareVersion(version, "0.5.x") >= 0) {
throw "Migrating collections from API version 0.4.0 is not supported yet";
// Make sure we don't alter the original object
let collection = Utils.deepClone(originalCollection);
// If collection has no id => seems to be an invalid collection => abort
if (typeof collection.id !== 'string' || collection.id.length === 0) {
return {};
}
var collection = Object.assign({}, originalCollection);
if (!Object.keys(collection).length) {
return collection;
// Update stac_version
if (!Versions.validate(collection.stac_version) || Versions.compare(collection.stac_version, "0.9.0", "<")) {
collection.stac_version = "0.9.0";
}
// convert v0.3 processes to v0.4 format
if (Utils.compareVersion(version, "0.3.x") === 0) {
// name => id
collection.id = collection.name;
delete collection.name;
// Add stac_version
collection.stac_version = '0.6.1';
// Rename provider => providers
if (Array.isArray(collection.provider)) {
collection.providers = collection.provider;
delete collection.provider;
// Add missing extent upfront. Makes the following code simpler as it works on the object.
if (!Utils.isObject(collection.extent)) {
collection.extent = {};
}
// convert v0.4 collections to latest version
if (Versions.compare(version, "0.4.x", "=")) {
// Restructure spatial extent
if (Array.isArray(collection.extent.spatial)) {
collection.extent.spatial = {
bbox: [
collection.extent.spatial
]
};
}
if (typeof collection.properties !== 'object') {
collection.properties = {};
// Restructure temporal extent
if (Array.isArray(collection.extent.temporal)) {
collection.extent.temporal = {
interval: [
collection.extent.temporal
]
};
}
// Migrate eo:bands
if (collection['eo:bands'] !== null && typeof collection['eo:bands'] === 'object' && !Array.isArray(collection['eo:bands'])) {
var bands = [];
for(let key in collection['eo:bands']) {
var band = Object.assign({}, collection['eo:bands'][key]);
band.name = key;
if (typeof band.resolution !== 'undefined' && typeof band.gsd === 'undefined') {
band.gsd = band.resolution;
delete band.resolution;
// move properties to other_properties
if (Utils.isObject(collection.properties)) {
if (!Utils.isObject(collection.other_properties)) {
collection.other_properties = {};
}
for(let key in collection.properties) {
collection.other_properties[key] = {
values: [
collection.properties[key]
]
};
}
}
delete collection.properties;
// now we can work on all properties and migrate to summaries
let props = Utils.isObject(collection.other_properties) ? collection.other_properties : {};
for(let key in props) {
let val = props[key];
if (Utils.isObject(val) && (Array.isArray(val.extent) || Array.isArray(val.values))) {
if (Array.isArray(val.extent)) {
props[key] = {
min: val.extent[0],
max: val.extent[1]
};
}
if (typeof band.wavelength !== 'undefined' && typeof band.center_wavelength === 'undefined') {
band.center_wavelength = band.wavelength;
delete band.wavelength;
else { // val.value is an array
let is2dArray = val.values.filter(v => !Array.isArray(v)).length === 0;
if (is2dArray) {
if (val.values.length < 2) {
props[key] = val.values[0];
}
else {
props[key] = val.values.reduce((a, b) => a.concat(b));
}
}
else {
props[key] = val.values;
}
}
bands.push(band);
}
collection['eo:bands'] = bands;
else {
// If not valid, move to top-level
if (typeof collection[key] === 'undefined') {
collection[key] = val;
}
delete props[key];
}
}
// Move all other properties into properties.
for (let key in collection) {
if (key.includes(':')) {
collection.properties[key] = collection[key];
delete collection[key];
delete collection.other_properties;
collection.summaries = Utils.isObject(collection.summaries) ? collection.summaries : {};
for(let key in props) {
let val = props[key];
if (key === 'sar:pass_direction') {
// Convert null to geostationary
val = val.map(v => v === null ? 'geostationary' : v);
}
// Convert arrays into separate fields as needed for some SAR fields
if ((key === 'sar:resolution' || key === 'sar:pixel_spacing' || key === 'sar:looks') && Array.isArray(val) && val.length >= 2) {
collection.summaries[key + '_range'] = val.slice(0,1);
collection.summaries[key + '_azimuth'] = val.slice(1,2);
if (val.length > 2) {
collection.summaries[key + '_equivalent_number'] = val.slice(2,3);
}
}
// Do the renaming of fields
else if (typeof fieldMap[key] === 'string') {
collection.summaries[fieldMap[key]] = val;
}
// Move invalid summaries to the top level
else if (moveToRoot.includes(key) && Array.isArray(val) && val.length === 1) {
collection[key] = val[0];
}
// Do the general conversion
else {
collection.summaries[key] = val;
}
}
}
// Add missing required fields
if (typeof collection.description !== 'string') {
collection.description = "";
}
if (!Utils.isObject(collection.extent.spatial)) {
collection.extent.spatial = {};
}
if (!Utils.isObject(collection.extent.temporal)) {
collection.extent.temporal = {};
}
if (typeof collection.license !== 'string') {
collection.license = "proprietary";
}
if (!Utils.isObject(collection.summaries)) {
collection.summaries = {};
}
if (!Utils.isObject(collection['cube:dimensions'])) {
collection['cube:dimensions'] = {};
}
// 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;
});
// Fix stac_extensions
var extensions = Array.isArray(collection.stac_extensions) ? collection.stac_extensions : [];
for(var key in collection) {
let ext = null;
let prefix = key.split(':', 1);
if (key === 'deprecated' || key === 'version') {
ext = 'version';
}
else if (typeof extMap[prefix] === 'string') {
ext = extMap[prefix];
}
if (ext !== null && !extensions.includes(ext)) {
extensions.push(ext);
}
}
extensions.sort();
collection.stac_extensions = extensions;
return collection;
}
};
}
module.exports = MigrateCollections;
const Utils = require('../utils.js');
const Versions = require('../versions.js');
var MigrateProcesses = {
class MigrateProcesses {
// Always returns a copy of the input process object
convertProcessToLatestSpec(originalProcess, version) {
if (!version || typeof version !== 'string') {
throw new Error("No version specified");
static convertProcessToLatestSpec(originalProcess, 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
var process = Object.assign({}, originalProcess);
let process = Utils.deepClone(originalProcess);
let isVersion03 = Utils.compareVersion(version, "0.3.x") === 0;
// name => id
if (isVersion03) {
process.id = process.name;
delete process.name;
}
// If process has no id => seems to be an invalid process, abort
// If process has no id => seems to be an invalid process => abort
if (typeof process.id !== 'string' || process.id.length === 0) {

@@ -26,2 +20,34 @@ return {};

// Convert the parameters from object to array
if (Versions.compare(version, "0.4.x", "=")) {
// Determine the parameter order
if (!Array.isArray(process.parameter_order) || process.parameter_order.length === 0) {
process.parameter_order = [];
for(let param in process.parameters) {
process.parameter_order.push(param);
}
}
// Upgrade parameters and convert from array to object
let params = [];
for(let name of process.parameter_order) {
// Add name
let obj = {name: name};
if (Utils.isObject(process.parameters[name])) {
Object.assign(obj, process.parameters[name]);
}
// Migrate from required to optional
if (!obj.required) {
obj.optional = true;
}
delete obj.required;
// Add to list of ordered params
params.push(obj);
}
delete process.parameter_order;
process.parameters = params;
}
// Set required field description if not a string

@@ -32,52 +58,28 @@ if (typeof process.description !== 'string') {

// Parameters
if (Utils.isObject(process.parameters)) {
for(var key in process.parameters) {
process.parameters[key] = upgradeParamAndReturn(process.parameters[key], version);
// Update parameters
if (Array.isArray(process.parameters)) {
for(let i in process.parameters) {
let param = process.parameters[i];
if (!Utils.isObject(param)) {
continue;
}
// Set required field description if not a string
if (typeof param.description !== 'string') {
param.description = "";
}
// Upgrade parameter schema
process.parameters[i] = upgradeSchema(param, version);
}
}
else {
process.parameters = {};
process.parameters = [];
}
// Return value
process.returns = upgradeParamAndReturn(process.returns, version);
if (isVersion03) {
// exception object
if (Utils.isObject(process.exceptions)) {
for(let key in process.exceptions) {
var e = process.exceptions[key];
if (typeof e.message === 'undefined') {
process.exceptions[key] = Object.assign({}, e, {
message: e.description
});
}
}
}
// examples object
if (Utils.isObject(process.examples)) {
var examples = [];
for(let key in process.examples) {
var old = process.examples[key];
var example = {
title: old.summary || key,
description: old.description
};
if (old.process_graph) {
example.process_graph = old.process_graph;
}
examples.push(example);
}
process.examples = examples;
}
// Fill parameter order
if (typeof process.parameters === 'object' && !Array.isArray(process.parameter_order)) {
var parameter_order = Object.keys(process.parameters);
if (parameter_order.length > 1) {
process.parameter_order = parameter_order;
}
}
// Update return value
if (!Utils.isObject(process.returns)) {
process.returns = {};
}
process.returns = upgradeSchema(process.returns, version, false);

@@ -87,37 +89,20 @@ return process;

};
}
function upgradeParamAndReturn(obj, version) {
// Not an object => return minimum required fields
if (!Utils.isObject(obj)) {
return {
description: "",
schema: {}
};
function upgradeSchema(obj, version, isParam = true) {
var schema = {};
if (obj.schema && typeof obj.schema === 'object') { // array or object?
schema = obj.schema;
}
var param = Object.assign({}, obj);
// v0.3 => v0.4: mime_type => media_type
if (Utils.compareVersion(version, "0.3.x") === 0 && typeof param.mime_type !== 'undefined') {
param.media_type = param.mime_type;
delete param.mime_type;
}
// Set required fields if not valid yet
if (typeof param.description !== 'string') {
param.description = "";
}
if (typeof param.schema !== 'object' || !param.schema) {
param.schema = {};
}
if (Utils.compareVersion(version, "0.4.x") <= 0) {
if (Versions.compare(version, "0.4.x", "=")) {
// Remove anyOf/oneOf wrapper
for(var type in {anyOf: null, oneOf: null}) {
if (Array.isArray(param.schema[type])) {
if (typeof param.schema.default !== 'undefined') {
param.default = param.schema.default;
for(let type of ['anyOf', 'oneOf']) {
if (Array.isArray(schema[type])) {
// Parameters only: Move default value to parameter-level
if (isParam && typeof schema.default !== 'undefined') {
obj.default = schema.default;
}
param.schema = param.schema[type];
// Move array one level up, removing anyOf and oneOf
schema = schema[type];
break;

@@ -127,39 +112,71 @@ }

// Remove default value from schema, add on parameter-level instead
var moveMediaType = (Utils.compareVersion(version, "0.4.x") <= 0 && typeof param.media_type !== 'undefined');
var schemas = Array.isArray(param.schema) ? param.schema : [param.schema];
for(var i in schemas) {
if (typeof schemas[i].default !== 'undefined') {
param.default = schemas[i].default;
delete schemas[i].default;
let moveMediaType = (Versions.compare(version, "0.4.x") <= 0 && typeof obj.media_type !== 'undefined');
let schemas = Array.isArray(schema) ? schema : [schema];
for(let subSchema of schemas) {
// Rename format to subtype recursively
subSchema = renameFormat(subSchema);
// Parameters only: Move default value to parameter-level
if (isParam && typeof subSchema.default !== 'undefined') {
obj.default = subSchema.default;
delete subSchema.default;
}
// v0.3 => v0.4: mime_type => media_type
// Replace media_type field with contentMediaType from JSON Schemas
if (moveMediaType) {
schemas[i].contentMediaType = param.media_type;
subSchema.contentMediaType = obj.media_type;
}
renameFormat(schemas[i]);
}
// Remove the media type, has been moved to JSON Schema above.
// Remove the media type
if (moveMediaType) {
delete param.media_type;
delete obj.media_type;
}
}
return param;
obj.schema = schema;
return obj;
}
function renameFormat(schema) {
for(var i in schema) {
if (i === 'format') {
schema.subtype = schema.format;
if (!['date-time', 'time', 'date', 'uri'].includes(schema.format)) {
delete schema.format;
}
if (Utils.isObject(schema) && typeof schema.type !== 'undefined' && typeof schema.format === 'string') {
switch(schema.format) {
case 'url':
schema.format = 'uri';
break;
case 'proj-definition':
schema.deprecated = true;
break;
case 'callback':
schema.format = 'process-graph';
if (Utils.isObject(schema.parameters)) {
let params = [];
for(let name in schema.parameters) {
let paramSchema = schema.parameters[name];
let param = {
name: name,
description: typeof paramSchema.description === 'string' ? paramSchema.description : "",
schema: paramSchema
};
params.push(param);
}
schema.parameters = params;
}
break;
}
else if (schema[i] && typeof schema[i] === 'object') {
renameFormat(schema[i]);
schema.subtype = schema.format;
// Leave format for "well-known" formats defined in JSON Schema
if (!['date-time', 'time', 'date', 'uri'].includes(schema.format)) {
delete schema.format;
}
}
for(let i in schema) {
if (schema[i] && typeof schema[i] === 'object') {
schema[i] = renameFormat(schema[i]);
}
}
return schema;
}
module.exports = MigrateProcesses;

@@ -1,40 +0,59 @@

const compareVersions = require('compare-versions');
class Utils {
var Utils = {
/**
* Checks whether a variable is a real object or not.
*
* This is a more strict version of `typeof x === 'object'` as this example would also succeeds for arrays and `null`.
* This function only returns `true` for real objects and not for arrays, `null` or any other data types.
*
* @param {*} obj - A variable to check.
* @returns {boolean} - `true` is the given variable is an object, `false` otherwise.
*/
static isObject(obj) {
return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
}
compareVersion(v1, v2) {
try {
return compareVersions(v1, v2);
} catch (error) {
return null;
}
},
/**
* Checks whether a variable is numeric.
*
* Numeric is every string with numeric data or a number, excluding NaN and finite numbers.
*
* @param {*} n - A variable to check.
* @returns {boolean} - `true` is the given variable is numeric, `false` otherwise.
*/
static isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
/**
* Deep clone for JSON-compatible data.
*
* @param {*} x
* @returns {*}
*/
static deepClone(x) {
return JSON.parse(JSON.stringify(x));
}
isObject(obj) {
return (typeof obj === 'object' && obj === Object(obj) && !Array.isArray(obj));
},
size(obj) {
if (typeof obj === 'object' && obj !== null) {
if (Array.isArray(obj)) {
return obj.length;
/**
* Normalize a URL (mostly handling slashes).
*
* @static
* @param {string} baseUrl - The URL to normalize
* @param {string} path - An optional path to add to the URL
* @returns {string} Normalized URL.
*/
static normalizeUrl(baseUrl, path = null) {
let url = baseUrl.replace(/\/$/, ""); // Remove trailing slash from base URL
if (typeof path === 'string') {
if (path.substr(0, 1) !== '/') {
path = '/' + path; // Add leading slash to path
}
else {
return Object.keys(obj).length;
}
url = url + path.replace(/\/$/, ""); // Remove trailing slash from path
}
return 0;
},
replacePlaceholders(message, variables = {}) {
if (typeof message === 'string' && this.isObject(variables)) {
for(var placeholder in variables) {
message = message.replace('{' + placeholder + '}', variables[placeholder]);
}
}
return message;
return url;
}
};
}
module.exports = Utils;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc