UNPKG

fabric-ias

Version:

Node.JS Service for Microsoft Fabric supporting infrastructure as code

172 lines (165 loc) 5.87 kB
"use strict"; const Base = require("./base"); const fs = require('fs'); const { Blob } = require('buffer'); const path = require('path'); /** * @class Libraries * @classdesc * Manages custom libraries in a Microsoft Fabric Environment. * Provides methods to retrieve, upload, delete, and replace libraries in both staging and published environments. * Extends the Base class for authentication and API request handling. * * @extends Base * * @property {string} id - The environment ID. * @property {string} endpoint - The API endpoint for the environment. * @property {Object} staging - The current staging environment libraries and configuration. * @property {Object} published - The current published environment libraries and configuration. */ class Libraries extends Base { /** * Constructs a Libraries instance for a given workspace and environment. * @param {AzOauth} OAuthHandler - OAuth handler for authentication. * @param {string} workspace_id - The workspace ID. * @param {string} environment_id - The environment ID. */ constructor(OAuthHandler, handler, workspace_id, environment_id) { super(OAuthHandler, handler); this.id = environment_id || ''; this.endpoint = `${this.endpoint}/workspaces/${workspace_id}/environments/${environment_id}`; this.staging = {}; this.published = {}; } /** * Retrieves libraries from Fabric Environment and parses them into a structured format. * Populates `this.staging` and `this.published` with environment YAML and library lists. * * @returns {Promise<Libraries|Error>} Returns this instance with updated properties. */ async get() { const [staging, published] = await Promise.all([this._getLib(true), this._getLib(false)]); this.staging = { environment: staging.data.environmentYml, libraries: staging.data.customLibraries.wheelFiles.concat(staging.data.customLibraries.pyFiles, staging.data.customLibraries.jarFiles, staging.data.customLibraries.rTarFiles) }; this.published = { // environment: published.environmentYml, // libraries: published.customLibraries.wheelFiles.concat( // published.customLibraries.pyFiles, // published.customLibraries.jarFiles, // published.customLibraries.rTarFiles // ) }; return this; } /** * Internal method to fetch libraries from Fabric Environment. * * @param {boolean} staging - If true, fetches staging libraries; otherwise, published libraries. * @returns {Promise<Object>} The environment data from the API. * @throws {Error} If the API response is invalid or contains an error. */ async _getLib(staging = false) { const staging_url = staging ? 'staging/' : ''; return await this._get(`/${staging_url}libraries`, {}, function (response) { if (response.data == undefined) throw Error('Invalid Response: Payload expected to contain libraries'); }); } /** * Deletes a file from the Fabric Environment Library (staging). * * @param {string} file - The filename to remove. * @returns {Promise<boolean|Error>} True if deleted, otherwise throws an error. */ async delete(file) { const options = { headers: { 'Content-Type': 'multipart/form-data' } }; await this._delete(`/staging/libraries?libraryToDelete=${file}`, options); return true; } /** * Uploads a file to the Fabric Environment Library (staging). * * @param {string} filePath - The path to the file to upload. * @returns {Promise<boolean|Error>} True if uploaded, otherwise throws an error. */ async upload(filePath) { const options = { headers: { 'Content-Type': 'multipart/form-data' } }; const form = new FormData(); try { const fileData = fs.readFileSync(filePath); const file = new Blob([fileData], { type: 'application/octet-stream' }); form.append('file', file, path.basename(filePath)); } catch (error) { this.parseError(error); } await this._post(`/staging/libraries`, form, options); return true; } /** * Replaces a library in the Fabric Environment Library (staging). * Deletes all matching libraries and uploads the new file. * Optionally invokes a callback at each step. * * @param {string} library - The library name or pattern to replace. * @param {string} filePath - The path to the new file. * @param {function} [callback] - Optional callback for progress updates. * @returns {Promise<void>} */ async replace(library, filePath, callback = null) { const obj = {}; if (Object.keys(this.staging).length === 0 || Object.keys(this.staging.libraries).length === 0) { if (callback != undefined) { callback("getLibrary", {}); } await this.get(); if (callback != undefined) { callback("getLibrary", this); } } const regex = new RegExp(`${library}`); const matches = this.staging.libraries.filter(item => regex.test(item)); if (matches.length !== 0) { for (const match of matches) { if (callback != undefined) { callback("delete", { file: match, status: "starting" }); } if ((await this.delete(match)) && callback != undefined) { callback("delete", { file: match, status: "deleted" }); } } } const file = path.basename(filePath); if (callback != undefined) { callback("upload", { file: file, status: "starting" }); } if ((await this.upload(filePath)) && callback != undefined) { callback("upload", { file: file, status: "uploaded" }); } } } module.exports = Libraries;