@intuitionrobotics/file-upload
Version:
File Uploader - Express & Typescript based backend framework
158 lines • 7.51 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseUploaderModule_Class = exports.FileStatus = void 0;
const ts_common_1 = require("@intuitionrobotics/ts-common");
const thunderstorm_1 = require("@intuitionrobotics/thunderstorm");
const RequestKey_UploadUrl = 'get-upload-url';
const RequestKey_UploadFile = 'upload-file';
var FileStatus;
(function (FileStatus) {
FileStatus["ObtainingUrl"] = "ObtainingUrl";
FileStatus["UrlObtained"] = "UrlObtained";
FileStatus["UploadingFile"] = "UploadingFile";
// I can assume that in between I upload and I get
// the push I'm processing the file in the be
FileStatus["PostProcessing"] = "PostProcessing";
FileStatus["Completed"] = "Completed";
FileStatus["Error"] = "Error";
})(FileStatus || (exports.FileStatus = FileStatus = {}));
class BaseUploaderModule_Class extends ts_common_1.Module {
constructor(httpModule, moduleName) {
super(moduleName);
this.files = {};
this.uploadQueue = new ts_common_1.Queue("File Uploader").setParallelCount(2);
this.uploadFiles = (response) => __awaiter(this, void 0, void 0, function* () {
// Subscribe
yield this.subscribeToPush(response);
response.forEach(r => {
const feId = r.tempDoc.feId;
this.uploadQueue.addItem(() => __awaiter(this, void 0, void 0, function* () {
yield this.uploadFile(r);
delete this.files[feId].file;
this.setFileInfo(feId, "progress", undefined);
//TODO: Probably need to set a timer here in case we dont get a push back (contingency)
}), () => {
this.setFileInfo(feId, "status", FileStatus.PostProcessing);
}, error => {
this.setFileInfo(feId, "status", FileStatus.Error);
this.setFileInfo(feId, "messageStatus", (0, ts_common_1.__stringify)(error));
});
});
});
this.uploadFile = (response) => __awaiter(this, void 0, void 0, function* () {
const feId = response.tempDoc.feId;
this.setFileInfo(feId, "status", FileStatus.UploadingFile);
this.setFileInfo(feId, "tempDoc", response.tempDoc);
const fileInfo = this.files[feId];
if (!fileInfo)
throw new ts_common_1.BadImplementationException(`Missing file with id ${feId} and name: ${response.tempDoc.name}`);
const request = this
.httpModule
.createRequest(thunderstorm_1.HttpMethod.PUT, RequestKey_UploadFile)
.setUrl(response.secureUrl)
// Don't change this because it replaces the default headers which we dont need
.setDefaultHeaders({ 'Content-Type': response.tempDoc.mimeType })
.setTimeout(20 * ts_common_1.Minute)
.setBody(fileInfo.file)
.setOnProgressListener((ev) => {
this.setFileInfo(feId, "progress", ev.loaded / ev.total);
});
this.setFileInfo(feId, "request", request);
yield request.executeSync();
});
this.httpModule = httpModule;
}
init() {
if (this.config.uploadQueueParallelCount)
this.uploadQueue.setParallelCount(this.config.uploadQueueParallelCount);
}
getFileInfo(id, key) {
return this.files[id] && this.files[id][key];
}
getFullFileInfo(id) {
return this.files[id];
}
setFileInfo(id, key, value) {
if (!this.files[id])
throw new ts_common_1.BadImplementationException(`Trying to set ${key} for non existent file with id: ${id}`);
this.files[id][key] = value;
this.files[id].statusCallBack(id, this.files[id].status);
}
uploadImpl(files, _bucketName, _pathPrefix) {
const body = files.map(fileData => {
const fileInfo = {
name: fileData.name,
mimeType: fileData.mimeType,
feId: (0, ts_common_1.generateHex)(32)
};
if (fileData.key)
fileInfo.key = fileData.key;
if (fileData.public)
fileInfo.public = fileData.public;
this.files[fileInfo.feId] = {
file: fileData.file,
fileName: fileData.file.name,
status: FileStatus.ObtainingUrl,
name: fileData.name,
statusCallBack: fileData.onFileStatusChanged
};
return fileInfo;
});
if (_bucketName)
this.getUrlEndpointWithBucketName({ files: body, pathPrefix: _pathPrefix, bucketName: _bucketName });
else
this.getUrlEndpoint(body);
return body;
}
getUrlEndpoint(body) {
this
.httpModule
.createRequest(thunderstorm_1.HttpMethod.POST, RequestKey_UploadUrl)
.setRelativeUrl('/v1/upload/get-url')
.setJsonBody(body)
.setOnError((request, resError) => {
body.forEach(f => {
this.setFileInfo(f.feId, "messageStatus", (0, ts_common_1.__stringify)(resError === null || resError === void 0 ? void 0 : resError.debugMessage));
this.setFileInfo(f.feId, "status", FileStatus.Error);
});
})
.execute((response) => __awaiter(this, void 0, void 0, function* () {
body.forEach(f => this.setFileInfo(f.feId, "status", FileStatus.UrlObtained));
if (!response)
return;
// Not a relevant await but still...
yield this.uploadFiles(response);
}));
}
getUrlEndpointWithBucketName(body) {
this
.httpModule
.createRequest(thunderstorm_1.HttpMethod.POST, RequestKey_UploadUrl)
.setRelativeUrl('/v1/upload/get-url-with-bucket-name')
.setJsonBody(body)
.setOnError((request, resError) => {
body.files.forEach(f => {
this.setFileInfo(f.feId, "messageStatus", (0, ts_common_1.__stringify)(resError === null || resError === void 0 ? void 0 : resError.debugMessage));
this.setFileInfo(f.feId, "status", FileStatus.Error);
});
})
.execute((response) => __awaiter(this, void 0, void 0, function* () {
body.files.forEach(f => this.setFileInfo(f.feId, "status", FileStatus.UrlObtained));
if (!response)
return;
// Not a relevant await but still...
yield this.uploadFiles(response);
}));
}
}
exports.BaseUploaderModule_Class = BaseUploaderModule_Class;
//# sourceMappingURL=BaseUploaderModule.js.map