UNPKG

fabric-ias

Version:

Node.JS Service for Microsoft Fabric supporting infrastructure as code

189 lines (179 loc) 6.92 kB
"use strict"; const merge = require('deepmerge'); const axios = require("axios"); const delay = require("./utils/delay"); /** * @class Base * @classdesc * Base class for interacting with the Microsoft Fabric API. * Provides common functionality for API clients, including: * - Storing the OAuth handler for authentication. * - Defining the base API endpoint. * - Providing standard content types for requests. * - Generating request options with appropriate headers. * - Standardized error handling for API requests. * * @property {AzOauth} OAuth - The OAuth handler instance. * @property {string} endpoint - The base URL for the Fabric API. * @property {Object} ContentType - Common content types used in API requests. * @property {Function|null} ErrorHandler - Optional custom error handler. */ class Base { /** * Constructs a Base instance for Microsoft Fabric API interaction. * @param {AzOauth} OAuthHandler - An object responsible for handling OAuth authentication. * @param {Function|null} [ErrorHandler=null] - Optional custom error handler function. */ constructor(OAuthHandler, ErrorHandler = null, retryAfter = 20000) { this.OAuth = OAuthHandler; this.ErrorHandler = ErrorHandler; this.endpoint = `https://api.fabric.microsoft.com/v1`; this._retry = retryAfter; this.ContentType = { JSON: 'application/json', FormUrlEncoded: 'application/x-www-form-urlencoded', Multipart: 'multipart/form-data' }; } /** * Calls delay to hold processing for a specified time. * @param {int} ts - The time in milliseconds to wait before proceeding. * @returns */ async wait(ts = null) { await delay(ts || this._retry); return this; } /** * Generates request options with authorization and content-type headers. * Merges any additional options provided. * * @async * @param {Object} [options={}] - Additional request options to merge with defaults. * @returns {Promise<Object>} The merged options object with headers set for authorization and content type. */ async Options(options = {}) { const defaults = { headers: { 'Content-Type': this.ContentType.JSON, 'Authorization': await this.OAuth.authorization() } }; return merge.all([defaults, options]); } /** * Sends a GET request to the specified endpoint. * @param {string} endpoint - The API endpoint path (relative to base). * @param {Object} [options={}] - Additional request options. * @param {function} [validator=null] - Validation Callback function to validate the resp. * @returns {Promise<Object>} The Axios resp object. * @throws {Error} If the request fails. */ async _get(endpoint, options = {}, validator = null) { const opts = await this.Options(options); try { const resp = await axios.get(`${this.endpoint}${endpoint}`, opts); if (validator) validator(resp); return resp; } catch (error) { this.parseError(error); } } /** * Sends a POST request to the specified endpoint. * @param {string} endpoint - The API endpoint path (relative to base). * @param {Object} [data={}] - The request payload. * @param {Object} [options={}] - Additional request options. * @param {function} [validator=null] - Validation Callback function to validate the resp. * @returns {Promise<Object>} The Axios resp object. * @throws {Error} If the request fails. */ async _post(endpoint, data = {}, options = {}, validator = null) { const opts = await this.Options(options); try { const resp = await axios.post(`${this.endpoint}${endpoint}`, data, opts); if (validator) validator(resp); return resp; } catch (error) { this.parseError(error); } } /** * Sends a PUT request to the specified endpoint. * @param {string} endpoint - The API endpoint path (relative to base). * @param {Object} [data={}] - The request payload. * @param {Object} [options={}] - Additional request options. * @param {function} [validator=null] - Validation Callback function to validate the resp. * @returns {Promise<Object>} The Axios resp object. * @throws {Error} If the request fails. */ async _put(endpoint, data = {}, options = {}, validator = null) { const opts = await this.Options(options); try { const resp = await axios.put(`${this.endpoint}${endpoint}`, data, opts); if (validator) validator(resp); return resp; } catch (error) { this.parseError(error); } } /** * Sends a DELETE request to the specified endpoint. * @param {string} endpoint - The API endpoint path (relative to base). * @param {Object} [options={}] - Additional request options. * @param {function} [validator=null] - Validation Callback function to validate the resp. * @returns {Promise<Object>} The Axios resp object. * @throws {Error} If the request fails. */ async _delete(endpoint, options = {}, validator = null) { const opts = await this.Options(options); try { const resp = await axios.delete(`${this.endpoint}${endpoint}`, opts); if (validator) validator(resp); return resp; } catch (error) { this.parseError(error); } } /** * Sends a PATCH request to the specified endpoint. * @param {string} endpoint - The API endpoint path (relative to base). * @param {Object} [data={}] - The request payload. * @param {Object} [options={}] - Additional request options. * @param {function} [validator=null] - Validation Callback function to validate the resp. * @returns {Promise<Object>} The Axios resp object. * @throws {Error} If the request fails. */ async _patch(endpoint, data = {}, options = {}, validator = null) { const opts = await this.Options(options); try { const resp = await axios.patch(`${this.endpoint}${endpoint}`, data, opts); if (validator) validator(resp); return resp; } catch (error) { this.parseError(error); } } /** * Handles errors from Axios requests. * If a custom ErrorHandler is provided, it will be called. * Otherwise, throws a formatted error. * @param {Error} error - The error object thrown by Axios. * @throws {Error} The formatted error. */ parseError(error) { if (error.resp && error.resp.data && error.resp.data.errorCode && error.resp.data.message) { if (this.ErrorHandler) { this.ErrorHandler(`${error.resp.data.errorCode}: ${error.resp.data.message}`, error.resp.data); return; } throw Error(`${error.resp.data.errorCode}: ${error.resp.data.message}`); } if (this.ErrorHandler) { this.ErrorHandler(`${error.message}`, error); return; } throw Error(error.message); } } module.exports = Base;