UNPKG

@finos/legend-server-marketplace

Version:
430 lines (382 loc) 13.8 kB
/** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { type PlainObject, AbstractServerClient, isNonEmptyString, } from '@finos/legend-shared'; import type { LightProvider, TerminalServicesResponse, FetchProductsParams, } from './models/Provider.js'; import type { DataProductSearchResponse } from './models/DataProductSearchResult.js'; import type { SubscriptionRequest, SubscriptionResponse, } from './models/Subscription.js'; import type { CartItem, CartItemRequest, CartItemResponse, CartSummary, DeleteCartItemResponse, VendorAddonsSearchParams, VendorAddonsSearchResponse, } from './models/Cart.js'; import type { OrderDetails } from './models/Order.js'; import type { FeedbackRequest, FeedbackResponse } from './models/Feedback.js'; import type { V1_EntitlementsLakehouseEnvironmentType } from '@finos/legend-graph'; import { type TerminalProductOrderResponse, OrderStatusCategory, } from './models/TerminalProductOrder.js'; import type { AutosuggestResponse } from './models/AutosuggestResult.js'; import type { TaxonomyTreeResponse } from './models/Taxonomy.js'; import { FieldSearchType, type FieldSearchRequest, type GroupedFieldSearchResponse, } from './models/FieldSearch.js'; import type { DatasetSearchResponse, FieldSearchResponse, } from './models/DatasetSearchResult.js'; import type { EntitySearchResponse } from './models/EntitySearchResult.js'; export interface TrendingDataProductEntry { dataProductId?: string; deploymentId?: string; dataProductType: string; productName: string; productDescription?: string; dataProductName?: string; groupId?: string; artifactId?: string; versionId?: string; dataProductPath?: string; originType?: string; producerEnvironmentName?: string; producerEnvironmentType?: string; dataProductSource?: string; licenseTo?: string; } export interface MarketplaceServerClientConfig { serverUrl: string; subscriptionUrl: string; } export class MarketplaceServerClient extends AbstractServerClient { subscriptionUrl: string; constructor(config: MarketplaceServerClientConfig) { super({ baseUrl: config.serverUrl, networkClientOptions: { // NOTE: with the way we setup this server, we allow any (*) origin for CORS // so here we have to explicit omit credentials // See https://fetch.spec.whatwg.org/#concept-request-credentials-mode credentials: 'omit', }, }); this.subscriptionUrl = config.subscriptionUrl; } // ------------------------------------------- Vendors ------------------------------------------- private _vendors = (): string => `${this.baseUrl}/v1/vendors`; getVendors = (): Promise<PlainObject<LightProvider>[]> => this.get(this._vendors()); private _products = (): string => `${this.baseUrl}/v1/workflow/products`; fetchProducts = async ( params: FetchProductsParams, ): Promise<PlainObject<TerminalServicesResponse>> => { const queryParams: Record<string, string | number | boolean> = { kerberos: params.kerberos, product_type: params.product_type, preferred_products: params.preferred_products, }; if (params.page_number !== undefined) { queryParams.page_number = params.page_number; } if (params.page_size !== undefined) { queryParams.page_size = params.page_size; } if (params.search !== undefined && params.search !== '') { queryParams.search = params.search; } return this.get<PlainObject<TerminalServicesResponse>>( this._products(), undefined, undefined, queryParams, ); }; // ------------------------------------------- Search ------------------------------------------- private _search = (): string => `${this.baseUrl}/v1/search`; private _autosuggest = (): string => `${this.baseUrl}/v1/autosuggest`; dataProductSearch = async ( query: string, lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, searchType: string = 'hybrid', searchFilters: string[] = [], pageSize: number = 12, pageNumber: number = 1, showAll: boolean = false, ): Promise<PlainObject<DataProductSearchResponse>> => { const filters = searchFilters.join('&search_filters='); const searchFilterParam = filters ? `&search_filters=${filters}` : ''; return this.get<PlainObject<DataProductSearchResponse>>( `${this._search()}/dataProducts/${lakehouseEnv}?query=${query}&search_type=${searchType}${searchFilterParam}&page_size=${pageSize}&page_number=${pageNumber}&include_filter_metadata=true&show_all=${showAll}`, ); }; fieldSearch = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, params: FieldSearchRequest, signal?: AbortSignal, ): Promise<PlainObject<GroupedFieldSearchResponse>> => this.get<PlainObject<GroupedFieldSearchResponse>>( `${this._search()}/fields/${lakehouseEnv}/grouped`, signal ? { signal } : {}, undefined, { query: params.query, search_type: params.searchType ?? FieldSearchType.HYBRID, page_size: params.pageSize ?? 12, page_number: params.pageNumber ?? 1, ...(params.dataProductTypes?.length ? { data_product_types: params.dataProductTypes } : {}), }, ); getAutosuggestions = async ( query: string, environment: string, limit: number = 5, signal?: AbortSignal, ): Promise<AutosuggestResponse> => this.get<AutosuggestResponse>( `${this._autosuggest()}/dataProducts/${environment}`, signal ? { signal } : {}, undefined, { query, limit }, ); datasetSearch = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, groupId: string, artifactId: string, versionId: string, path: string, query: string, options?: { searchType?: string; pageSize?: number; pageNumber?: number }, ): Promise<PlainObject<DatasetSearchResponse>> => this.get<PlainObject<DatasetSearchResponse>>( `${this._search()}/datasets/${lakehouseEnv}/legacy`, undefined, undefined, { group_id: groupId, artifact_id: artifactId, version_id: versionId, path, query, search_type: options?.searchType ?? 'hybrid', page_size: options?.pageSize ?? 20, page_number: options?.pageNumber ?? 1, }, ); legacyFieldSearch = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, groupId: string, artifactId: string, versionId: string, path: string, options?: { searchType?: string; pageSize?: number; pageNumber?: number }, ): Promise<PlainObject<FieldSearchResponse>> => this.get<PlainObject<FieldSearchResponse>>( `${this._search()}/fields/${lakehouseEnv}/legacy`, undefined, undefined, { group_id: groupId, artifact_id: artifactId, version_id: versionId, path, search_type: options?.searchType ?? 'hybrid', page_size: options?.pageSize ?? 20, page_number: options?.pageNumber ?? 1, }, ); entitySearch = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, query: string, options?: { groupId?: string; artifactId?: string; versionId?: string; path?: string; dataProductId?: string; deploymentId?: string; searchType?: string; pageSize?: number; pageNumber?: number; includePrimitiveFields?: boolean; }, ): Promise<PlainObject<EntitySearchResponse>> => this.get<PlainObject<EntitySearchResponse>>( `${this._search()}/entities/${lakehouseEnv}`, undefined, undefined, { query, group_id: options?.groupId, artifact_id: options?.artifactId, version_id: options?.versionId, path: options?.path, data_product_id: options?.dataProductId, deployment_id: options?.deploymentId, search_type: options?.searchType ?? 'hybrid', page_size: options?.pageSize ?? 10, page_number: options?.pageNumber ?? 1, include_primitive_fields: options?.includePrimitiveFields ?? true, }, ); // ------------------------------------------- Trending ------------------------------------------- private readonly _analytics = (): string => `${this.baseUrl}/v1/analytics`; getTrendingDataProducts = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, ): Promise<TrendingDataProductEntry[]> => this.get<TrendingDataProductEntry[]>( `${this._analytics()}/top-products/${lakehouseEnv}`, undefined, undefined, ); // ------------------------------------------- Taxonomy ------------------------------------------- private _taxonomyTree = (): string => `${this.baseUrl}/v1/taxonomy/tree`; getTaxonomyTree = async ( lakehouseEnv: V1_EntitlementsLakehouseEnvironmentType, searchQuery?: string | undefined, refresh: boolean = false, ): Promise<TaxonomyTreeResponse> => { const queryParams: Record<string, string | boolean> = { refresh, }; if (searchQuery) { queryParams.search_query = searchQuery; } return this.get<TaxonomyTreeResponse>( `${this._taxonomyTree()}/${lakehouseEnv}`, undefined, undefined, queryParams, ); }; // ------------------------------------------- Subscriptions ----------------------------------------- private _subscriptions = (user: string): string => `${this.baseUrl}/v1/service/subscription/${user}`; getSubscriptions = async ( user: string, ): Promise<PlainObject<SubscriptionResponse>> => this.get<PlainObject<SubscriptionResponse>>(this._subscriptions(user)); cancelSubscriptions = async ( cancellationRequest: SubscriptionRequest, ): Promise<PlainObject<{ message: string }>> => this.post( `${this.baseUrl}/v1/workflow/cancel/subscription`, cancellationRequest, ); // ------------------------------------------- Cart ------------------------------------------- private _cart = (user: string): string => `${this.baseUrl}/v1/cart/${user}`; getCart = async ( user: string, ): Promise<PlainObject<Record<number, CartItem[]>>> => this.get<PlainObject<Record<number, CartItem[]>>>(this._cart(user)); getCartSummary = async (user: string): Promise<PlainObject<CartSummary>> => this.get<PlainObject<CartSummary>>(`${this._cart(user)}/summary`); clearCart = async (user: string): Promise<void> => this.delete(this._cart(user)); deleteCartItem = async ( user: string, cartId: number, confirmDelete?: boolean, ): Promise<PlainObject<DeleteCartItemResponse>> => this.delete( `${this._cart(user)}/item/${cartId}`, {}, {}, undefined, confirmDelete ? { confirm_delete: true } : undefined, ); addToCart = async ( user: string, cartItemData: CartItemRequest, ): Promise<PlainObject<CartItemResponse>> => this.post(this._cart(user), cartItemData); searchVendorAddons = async ( user: string, providerName: string, params?: VendorAddonsSearchParams, signal?: AbortSignal, ): Promise<PlainObject<VendorAddonsSearchResponse>> => { const queryParams: Record<string, string | number | boolean> = {}; if (params?.page !== undefined) { queryParams.page = params.page; } if (params?.page_size !== undefined) { queryParams.page_size = params.page_size; } if (isNonEmptyString(params?.search)) { queryParams.search = params.search; } if (params?.sort_by_price !== undefined) { queryParams.sort_by_price = params.sort_by_price; } return this.get<PlainObject<VendorAddonsSearchResponse>>( `${this._cart(user)}/vendor-addons/${encodeURIComponent(providerName)}`, signal ? { signal } : {}, undefined, queryParams, ); }; submitOrder = async ( user: string, orderData: OrderDetails, ): Promise<PlainObject<unknown>> => this.post(`${this.baseUrl}/v1/workflow/create/order`, orderData); // ------------------------------------------- Orders ------------------------------------------- private _orders = (): string => `${this.baseUrl}/v1/workflow/fetch/orders`; fetchOrders = async ( user: string, category: OrderStatusCategory = OrderStatusCategory.OPEN, ): Promise<PlainObject<TerminalProductOrderResponse>> => this.get<PlainObject<TerminalProductOrderResponse>>( this._orders(), undefined, undefined, { kerberos: user, category, }, ); cancelOrder = async (cancelData: { order_id: string; kerberos: string; comments: string; process_instance_id: string; }): Promise<PlainObject<{ status_code: number; message: string }>> => this.post(`${this.baseUrl}/v1/workflow/cancel/order`, cancelData); // ------------------------------------------- Feedback ------------------------------------------- private _feedback = (): string => `${this.baseUrl}/v1/feedback`; submitFeedback = async ( feedbackData: FeedbackRequest, ): Promise<PlainObject<FeedbackResponse>> => this.post(this._feedback(), feedbackData); }