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
JavaScript
;
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
});