import { URL } from "whatwg-url" import { DDO } from "../ddo/DDO" import DID from "../ocean/DID" import { Instantiable, InstantiableConfig } from "../Instantiable.abstract" const apiPath = "/api/v1/aquarius/assets/ddo" export interface QueryResult { results: DDO[] page: number totalPages: number totalResults: number } export interface SearchQuery { text?: string offset: number page: number query: {[property: string]: string | number | string[] | number[]} sort: {[jsonPath: string]: number} } /** * Provides a interface with Aquarius. * Aquarius provides an off-chain database store for metadata about data assets. */ export class Aquarius extends Instantiable { private get url() { return this.config.aquariusUri } constructor(config: InstantiableConfig) { super() this.setInstanceConfig(config) } public async getAccessUrl(accessToken: any, payload: any): Promise { const accessUrl: string = await this.ocean.utils.fetch .post(`${accessToken.service_endpoint}/${accessToken.resource_id}`, payload) .then((response: any): string => { if (response.ok) { return response.text() } this.logger.error("Failed: ", response.status, response.statusText) return null }) .then((consumptionUrl: string): string => { this.logger.error("Success accessing consume endpoint: ", consumptionUrl) return consumptionUrl }) .catch((error) => { this.logger.error("Error fetching the data asset consumption url: ", error) return null }) return accessUrl } /** * Search over the DDOs using a query. * @param {SearchQuery} query Query to filter the DDOs. * @return {Promise} */ public async queryMetadata(query: SearchQuery): Promise { const result: QueryResult = await this.ocean.utils.fetch .post(`${this.url}${apiPath}/query`, JSON.stringify(query)) .then((response: any) => { if (response.ok) { return response.json() as DDO[] } this.logger.error("queryMetadata failed:", response.status, response.statusText) return this.transformResult() }) .then((results) => { return this.transformResult(results) }) .catch((error) => { this.logger.error("Error fetching querying metadata: ", error) return this.transformResult() }) return result } /** * Search over the DDOs using a query. * @param {SearchQuery} query Query to filter the DDOs. * @return {Promise} */ public async queryMetadataByText(query: SearchQuery): Promise { const fullUrl = new URL(`${this.url}${apiPath}/query`) fullUrl.searchParams.append("text", query.text) fullUrl.searchParams.append("sort", decodeURIComponent(JSON.stringify(query.sort))) fullUrl.searchParams.append("offset", query.offset.toString()) fullUrl.searchParams.append("page", query.page.toString()) const result: QueryResult = await this.ocean.utils.fetch .get(fullUrl) .then((response: any) => { if (response.ok) { return response.json() as DDO[] } this.logger.log("queryMetadataByText failed:", response.status, response.statusText) return this.transformResult() }) .then((results) => { return this.transformResult(results) }) .catch((error) => { this.logger.error("Error fetching querying metadata by text: ", error) return this.transformResult() }) return result } /** * Stores a DDO in Aquarius. * @param {DDO} ddo DDO to be stored. * @return {Promise} Final DDO. */ public async storeDDO(ddo: DDO): Promise { const fullUrl = `${this.url}${apiPath}` const result: DDO = await this.ocean.utils.fetch .post(fullUrl, DDO.serialize(ddo)) .then((response: any) => { if (response.ok) { return response.json() } this.logger.error("storeDDO failed:", response.status, response.statusText, ddo) return null as DDO }) .then((response: DDO) => { return new DDO(response) as DDO }) .catch((error) => { this.logger.error("Error fetching querying metadata: ", error) return null as DDO }) return result } /** * Retrieves a DDO by DID. * @param {DID} did DID of the asset. * @return {Promise} DDO of the asset. */ public async retrieveDDO(did: DID): Promise { const fullUrl = `${this.url}${apiPath}/${did.getDid()}` const result = await this.ocean.utils.fetch .get(fullUrl) .then((response: any) => { if (response.ok) { return response.json() } this.logger.log("retrieveDDO failed:", response.status, response.statusText, did) return null as DDO }) .then((response: DDO) => { return new DDO(response) as DDO }) .catch((error) => { this.logger.error("Error fetching querying metadata: ", error) return null as DDO }) return result } public getServiceEndpoint(did: DID) { return `${this.url}/api/v1/aquarius/assets/ddo/did:op:${did.getId()}` } private transformResult( {results, page, total_pages, total_results}: any = {result: [], page: 0, total_pages: 0, total_results: 0}, ): QueryResult { return { results: (results || []).map((ddo) => new DDO(ddo as DDO)), page, totalPages: total_pages, totalResults: total_results, } } }