From 44cd0e3719b85dfcf3c1dc7fb5280c6bf8bf5f29 Mon Sep 17 00:00:00 2001 From: Matthias Mohr Date: Fri, 3 Jan 2025 20:58:10 +0100 Subject: [PATCH] Add self URLs for pagination --- openeo.d.ts | 21 ++++++++++++++++++--- src/connection.js | 45 +++++++++++++++++++++++++++++++++++++-------- src/typedefs.js | 3 ++- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/openeo.d.ts b/openeo.d.ts index aea9c16..b246367 100644 --- a/openeo.d.ts +++ b/openeo.d.ts @@ -2012,6 +2012,7 @@ declare module OpenEO { * List all collections available on the back-end. * * The collections returned always comply to the latest STAC version (currently 1.0.0). + * This function adds a self link to the response if not present. * * @async * @returns {Promise} A response compatible to the API specification. @@ -2021,7 +2022,8 @@ declare module OpenEO { /** * Paginate through the collections available on the back-end. * - * The collections returned always comply to the latest STAC version (currently 1.0.0). + * The collections returned always complies to the latest STAC version (currently 1.0.0). + * This function adds a self link to the response if not present. * * @async * @param {?number} [limit=50] - The number of collections per request/page as integer. If `null`, requests all collections. @@ -2086,6 +2088,8 @@ declare module OpenEO { * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given. * The namespaces are then listed in the property `namespaces`. * + * This function adds a self link to the response if not present. + * * @async * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL! * @returns {Promise} - A response compatible to the API specification. @@ -2101,6 +2105,8 @@ declare module OpenEO { * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given. * The namespaces are then listed in the property `namespaces`. * + * This function adds a self link to the response if not present. + * * @async * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL! * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes. @@ -2490,9 +2496,10 @@ declare module OpenEO { * @protected * @param {Array.<*>} arr * @param {object.} response + * @param {string} selfUrl * @returns {ResponseArray} */ - protected _toResponseArray(arr: Array, response: object): ResponseArray; + protected _toResponseArray(arr: Array, response: object, selfUrl: string): ResponseArray; /** * Get the a link with the given rel type. * @@ -2511,6 +2518,14 @@ declare module OpenEO { * @returns {string | null} */ protected _getNextLink(response: AxiosResponse): string | null; + /** + * Add a self link to the response if not present. + * + * @param {object} data - The body of the response as an object. + * @param {string} selfUrl - The URL of the current request. + * @returns {object} The modified object. + */ + _addSelfLink(data: object, selfUrl: string): object; /** * Makes all links in the list absolute. * @@ -2974,7 +2989,7 @@ declare module OpenEO { /** * An array, but enriched with additional details from an openEO API response. * - * Adds two properties: `links` and `federation:missing`. + * Adds three properties: `url`, `links` and `federation:missing`. */ export type ResponseArray = any; export type ServiceType = object; diff --git a/src/connection.js b/src/connection.js index 87fb34b..3a21888 100644 --- a/src/connection.js +++ b/src/connection.js @@ -221,6 +221,7 @@ class Connection { * List all collections available on the back-end. * * The collections returned always comply to the latest STAC version (currently 1.0.0). + * This function adds a self link to the response if not present. * * @async * @returns {Promise} A response compatible to the API specification. @@ -234,7 +235,8 @@ class Connection { /** * Paginate through the collections available on the back-end. * - * The collections returned always comply to the latest STAC version (currently 1.0.0). + * The collections returned always complies to the latest STAC version (currently 1.0.0). + * This function adds a self link to the response if not present. * * @async * @param {?number} [limit=50] - The number of collections per request/page as integer. If `null`, requests all collections. @@ -256,7 +258,7 @@ class Connection { return collection; }); } - yield response.data; + yield this._addSelfLink(response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -369,6 +371,8 @@ class Connection { * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given. * The namespaces are then listed in the property `namespaces`. * + * This function adds a self link to the response if not present. + * * @async * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL! * @returns {Promise} - A response compatible to the API specification. @@ -388,6 +392,8 @@ class Connection { * Note: The list of namespaces can be retrieved by calling `listProcesses` without a namespace given. * The namespaces are then listed in the property `namespaces`. * + * This function adds a self link to the response if not present. + * * @async * @param {?string} [namespace=null] - Namespace of the processes (default to `null`, i.e. pre-defined processes). EXPERIMENTAL! * @param {?number} [limit=50] - The number of processes per request/page as integer. If `null`, requests all processes. @@ -416,7 +422,7 @@ class Connection { response.data.processes[i] = this.processes.get(response.data.processes[i].id, namespace); } - yield response.data; + yield this._addSelfLink(response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -713,7 +719,7 @@ class Connection { const files = response.data.files.map( f => new UserFile(this, f.path).setAll(f) ); - yield this._toResponseArray(files, response.data); + yield this._toResponseArray(files, response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -854,7 +860,7 @@ class Connection { const jsonProcesses = oldProcesses.length > 0 ? newProcesses.map(p => p.toJSON()) : response.data.processes; this.processes.addAll(jsonProcesses, 'user'); - yield this._toResponseArray(newProcesses, response.data); + yield this._toResponseArray(newProcesses, response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -1004,7 +1010,7 @@ class Connection { } return job.setAll(newJob); }); - yield this._toResponseArray(newJobs, response.data); + yield this._toResponseArray(newJobs, response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -1092,7 +1098,7 @@ class Connection { } return service.setAll(newService); }); - yield this._toResponseArray(newServices, response.data); + yield this._toResponseArray(newServices, response.data, nextUrl); nextUrl = this._getNextLink(response); } while (nextUrl); } @@ -1157,9 +1163,11 @@ class Connection { * @protected * @param {Array.<*>} arr * @param {object.} response + * @param {string} selfUrl * @returns {ResponseArray} */ - _toResponseArray(arr, response) { + _toResponseArray(arr, response, selfUrl) { + arr.url = selfUrl; arr.links = Array.isArray(response.links) ? response.links : []; arr['federation:missing'] = Array.isArray(response['federation:missing']) ? response['federation:missing'] : []; return arr; @@ -1199,6 +1207,27 @@ class Connection { return this._getLinkHref(links, 'next'); } + /** + * Add a self link to the response if not present. + * + * @param {object} data - The body of the response as an object. + * @param {string} selfUrl - The URL of the current request. + * @returns {object} The modified object. + */ + _addSelfLink(data, selfUrl) { + if (!Utils.isObject(data)) { + return data; + } + if (!Array.isArray(data.links)) { + data.links = []; + } + const selfLink = data.links.find(l => Utils.isObject(l) && l.rel === 'self'); + if (!selfLink) { + data.links.push({rel: 'self', href: selfUrl}); + } + return data; + } + /** * Makes all links in the list absolute. * diff --git a/src/typedefs.js b/src/typedefs.js index 0fd0a10..ce3249f 100644 --- a/src/typedefs.js +++ b/src/typedefs.js @@ -213,11 +213,12 @@ /** * An array, but enriched with additional details from an openEO API response. * - * Adds two properties: `links` and `federation:missing`. + * Adds three properties: `url`, `links` and `federation:missing`. * * @typedef ResponseArray * @augments Array * @type {Array.<*>} + * @property {string} url The URL from which the data was requested. * @property {Array.} links A list of related links. * @property {Array.} ["federation:missing"] A list of backends from the federation that are missing in the response data. */