UNPKG

spheron-storage-dusan

Version:

Typescript library for uploading files or directory to IPFS, Filecoin or Arweave via Spheron

296 lines (289 loc) 10.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/index.ts var src_exports = {}; __export(src_exports, { ProtocolEnum: () => ProtocolEnum, default: () => SpheronClient }); module.exports = __toCommonJS(src_exports); // src/upload-manager/index.ts var import_axios = __toESM(require("axios")); var import_p_limit = __toESM(require("p-limit")); // src/enums.ts var ProtocolEnum = /* @__PURE__ */ ((ProtocolEnum2) => { ProtocolEnum2["ARWEAVE"] = "arweave"; ProtocolEnum2["FILECOIN"] = "ipfs-filecoin"; ProtocolEnum2["IPFS"] = "ipfs"; return ProtocolEnum2; })(ProtocolEnum || {}); // src/upload-manager/upload-context.ts var import_fs = __toESM(require("fs")); var import_form_data = __toESM(require("form-data")); var import_path = __toESM(require("path")); var PayloadCreator = class { constructor(path2, payloadSize) { this.path = path2; this.payloadSize = payloadSize || 1024 * 1024 * 5; } createPayloads() { return __async(this, null, function* () { const uploadContext = { payloads: new Array(), currentPayload: null, currentPayloadSize: 0, totalSize: 0 }; yield this.fillUploadContext(this.path, "./", uploadContext, true); if (uploadContext.currentPayload) { uploadContext.payloads.push(uploadContext.currentPayload); } return { payloads: uploadContext.payloads, totalSize: uploadContext.totalSize }; }); } fillUploadContext(pathToFile, rootPath, uploadContext, isRoot) { return __async(this, null, function* () { const stat = yield import_fs.default.promises.stat(pathToFile); if (stat.isFile()) { const fileName = import_path.default.basename(pathToFile); this.processFile(pathToFile, rootPath + fileName, stat, uploadContext); return; } const files = yield import_fs.default.promises.readdir(pathToFile); for (const file of files) { yield this.fillUploadContext( `${pathToFile}/${file}`, isRoot ? "./" : `${rootPath}${import_path.default.basename(pathToFile)}/`, uploadContext, false ); } }); } processFile(fullPath, uploadPath, stat, uploadContext) { return __async(this, null, function* () { uploadContext.totalSize += stat.size; if (stat.size > this.payloadSize) { const numOfChunks = Math.ceil(stat.size / this.payloadSize); for (let i = 0; i < numOfChunks; i++) { const start = i * this.payloadSize; const end = start + this.payloadSize - 1; const form = new import_form_data.default(); form.append( `chunk-${i}-${numOfChunks}`, import_fs.default.createReadStream(fullPath, { start, end }), { filepath: uploadPath } ); uploadContext.payloads.push(form); } } else { if (!uploadContext.currentPayload) { uploadContext.currentPayload = new import_form_data.default(); } uploadContext.currentPayload.append( "files", import_fs.default.createReadStream(fullPath), { filepath: uploadPath } ); uploadContext.currentPayloadSize += stat.size; if (uploadContext.currentPayloadSize > this.payloadSize) { uploadContext.payloads.push(uploadContext.currentPayload); uploadContext.currentPayload = null; uploadContext.currentPayloadSize = 0; } } }); } }; // src/upload-manager/index.ts var UploadManager = class { constructor(configuration) { this.uploadApiUrl = "https://api-dev.spheron.network"; this.configuration = configuration; } upload(configuration) { return __async(this, null, function* () { this.validateUploadConfiguration(configuration); const { deploymentId, payloadSize, parallelUploadCount } = yield this.startDeployment( configuration.protocol, configuration.name, configuration.organizationId ); configuration.onUploadInitiated && configuration.onUploadInitiated(deploymentId); const payloadCreator = new PayloadCreator(configuration.path, payloadSize); const { payloads, totalSize } = yield payloadCreator.createPayloads(); const uploadPayloadsResult = yield this.uploadPayloads( deploymentId, payloads, parallelUploadCount, totalSize, configuration.onChunkUploaded ); const result = yield this.finalizeUploadDeployment( deploymentId, uploadPayloadsResult.success ); if (!result.success) { throw new Error(`Upload failed. ${result.message}`); } return { uploadId: result.deploymentId, bucketId: result.projectId, protocolLink: result.sitePreview, dynamicLinks: result.affectedDomains }; }); } startDeployment(protocol, projectName, organizationId) { return __async(this, null, function* () { var _a, _b; try { let url = `${this.uploadApiUrl}/v1/upload-deployment?protocol=${protocol}&project=${projectName}`; if (organizationId) { url += `&organization=${organizationId}`; } const response = yield import_axios.default.post(url, {}, this.getAxiosRequestConfig()); return response.data; } catch (error) { const errorMessage = ((_b = (_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || (error == null ? void 0 : error.message); throw new Error(errorMessage); } }); } uploadPayloads(deploymentId, payloads, parallelUploadCount, totalSize, onChunkUploaded) { return __async(this, null, function* () { let errorFlag = false; const limit = (0, import_p_limit.default)(parallelUploadCount); const uploadPayload = (payload, deploymentId2) => __async(this, null, function* () { try { if (errorFlag) { return; } const { data } = yield import_axios.default.post( `${this.uploadApiUrl}/v1/upload-deployment/${deploymentId2}/data`, payload, this.getAxiosRequestConfig() ); onChunkUploaded && onChunkUploaded(data.uploadSize, totalSize); } catch (error) { errorFlag = true; } }); yield Promise.all( payloads.map( (payload) => limit(() => uploadPayload(payload, deploymentId)) ) ); return { success: !errorFlag }; }); } finalizeUploadDeployment(deploymentId, upload) { return __async(this, null, function* () { var _a, _b; try { const response = yield import_axios.default.post( `${this.uploadApiUrl}/v1/upload-deployment/${deploymentId}/finish?action=${upload ? "UPLOAD" : "CANCEL"}`, {}, this.getAxiosRequestConfig() ); return response.data; } catch (error) { const errorMessage = ((_b = (_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || (error == null ? void 0 : error.message); throw new Error(errorMessage); } }); } validateUploadConfiguration(configuration) { const supportedProtocols = Object.values(ProtocolEnum); if (supportedProtocols.indexOf(configuration.protocol) === -1) { throw new Error( `Protocol '${configuration.protocol}' is not supported. Supported protocols are [${supportedProtocols.join( ", " )}].` ); } if (!configuration.name) { throw new Error("Name is not provided."); } } getAxiosRequestConfig() { return { headers: { Authorization: `Bearer ${this.configuration.token}` } }; } }; var upload_manager_default = UploadManager; // src/index.ts var SpheronClient = class { constructor(configuration) { this.configuration = configuration; } upload(path2, configuration) { return __async(this, null, function* () { const uploadManager = new upload_manager_default(this.configuration); return yield uploadManager.upload({ path: path2, name: configuration.name, protocol: configuration.protocol, organizationId: configuration.organizationId, onChunkUploaded: configuration.onChunkUploaded, onUploadInitiated: configuration.onUploadInitiated }); }); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ProtocolEnum });