UNPKG

@mcdevsl/superset-ui

Version:
137 lines (127 loc) 4.42 kB
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 rison from 'rison'; import { SupersetClient, Payload as SupersetPayload, JsonObject, JsonValue, ParseMethod, Endpoint, Method, RequestBase, } from '../../../connection'; import handleError, { ErrorInput } from './handleError'; import { SupersetApiRequestOptions, SupersetApiErrorPayload, ParsedResponseType } from './types'; const validRequestTypes = new Set(['form', 'json', 'search', 'rison']); interface SupersetApiFactoryOptions extends Omit<RequestBase, 'url'> { /** * API endpoint, must be relative. */ endpoint: Endpoint; /** * Request method: 'GET' | 'POST' | 'DELETE' | 'PUT' | ... */ method: Method; /** * How to send the payload: * - form: set request.body as FormData * - json: as JSON string with request Content-Type header set to application/json * - search: add to search params */ requestType?: 'form' | 'json' | 'search' | 'rison'; } function isPayloadless(method?: Method) { return !method || method === 'GET' || method === 'DELETE' || method === 'HEAD'; } /** * Generate an API caller with predefined configs/typing and consistent * return values. */ export default function makeApi< Payload = SupersetPayload, Result = JsonObject, T extends ParseMethod = ParseMethod >({ endpoint, method, requestType: requestType_, responseType, processResponse, ...requestOptions }: SupersetApiFactoryOptions & { /** * How to parse response, choose from: 'json' | 'text' | 'raw'. */ responseType?: T; /** * Further process parsed response */ processResponse?(result: ParsedResponseType<T>): Result; }) { // use `search` payload (searchParams) when it's a GET request const requestType = requestType_ || (isPayloadless(method) ? 'search' : 'json'); if (!validRequestTypes.has(requestType)) { throw new Error( `Invalid request payload type, choose from: ${[...validRequestTypes].join(' | ')}`, ); } async function request( payload: Payload, { client = SupersetClient }: SupersetApiRequestOptions = { client: SupersetClient }, ): Promise<Result> { try { const requestConfig = { ...requestOptions, method, endpoint, }; if (requestType === 'search') { requestConfig.searchParams = payload; } else if (requestType === 'rison') { requestConfig.endpoint = `${endpoint}?q=${rison.encode(payload)}`; } else if (requestType === 'form') { requestConfig.postPayload = payload; } else { requestConfig.jsonPayload = payload; } let result: JsonValue | Response; const response = await client.request({ ...requestConfig, parseMethod: 'raw' }); if (responseType === 'text') { result = await response.text(); } else if (responseType === 'raw' || responseType === null) { result = response; } else { result = await response.json(); // if response json has an "error" field if (result && typeof result === 'object' && 'error' in result) { return handleError(result as SupersetApiErrorPayload); } } const typedResult = result as ParsedResponseType<T>; return (processResponse ? processResponse(typedResult) : typedResult) as Result; } catch (error) { return handleError(error as ErrorInput); } } request.method = method; request.endpoint = endpoint; request.requestType = requestType; return request; }