@nu-art/file-upload
Version:
File Uploader - Express & Typescript based backend framework
156 lines (155 loc) • 6.74 kB
JavaScript
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleBase_AssetUploader = void 0;
/*
* Permissions management system, define access level for each of
* your server apis, and restrict users by giving them access levels
*
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const ts_common_1 = require("@nu-art/ts-common");
const thunderstorm_1 = require("@nu-art/thunderstorm");
const shared_1 = require("../../shared");
class ModuleBase_AssetUploader extends ts_common_1.Module {
constructor() {
super();
this.files = {};
this.uploadQueue = new ts_common_1.Queue('File Uploader').setParallelCount(1);
this.dispatch_fileStatusChange = new ts_common_1.Dispatcher('__onFileStatusChanged');
this.uploadFiles = async (response) => {
// Subscribe
await this.subscribeToPush(response);
response.forEach(r => {
const feId = r.asset.feId;
this.uploadQueue.addItem(async () => {
await this.uploadFile(r);
delete this.files[feId].file;
this.setFileInfo(feId, { progress: 0 });
//TODO: Probably need to set a timer here in case we dont get a push back (contingency)
}, () => {
this.setFileInfo(feId, { status: shared_1.FileStatus.WaitingForProcessing });
if (this.config.manualProcessTriggering)
this.processAssetManually(feId);
}, error => {
this.setFileInfo(feId, {
messageStatus: (0, ts_common_1.__stringify)(error),
status: shared_1.FileStatus.Error
});
});
});
};
this.uploadFile = async (response) => {
const feId = response.asset.feId;
this.setFileInfo(feId, {
status: shared_1.FileStatus.UploadingFile,
asset: response.asset
});
const fileInfo = this.files[feId];
if (!fileInfo)
throw new ts_common_1.BadImplementationException(`Missing file with id ${feId} and name: ${response.asset.name}`);
const request = this.createRequest(shared_1.ApiDef_UploadFile)
.setUrl(response.signedUrl)
.setHeader(thunderstorm_1.HeaderKey_ContentType, response.asset.mimeType)
.setTimeout(20 * ts_common_1.Minute)
.setBody(fileInfo.file)
.setOnProgressListener((ev) => {
this.setFileInfo(feId, { progress: ev.loaded / ev.total });
});
fileInfo.request = request;
await request.executeSync();
// const request = this.vv1.uploadFile(fileInfo.file, undefined as never)
// .setUrl(response.signedUrl);
// const request = this
// .httpModule
// .createRequest(HttpMethod.PUT, RequestKey_UploadFile, feId)
};
this.processAssetManually = (feId) => {
const request = this.vv1.processAssetManually({ feId });
// const request = this
// .httpModule
// .createRequest<Api_ProcessAssetManually>(HttpMethod.GET, RequestKey_ProcessAssetManually, feId)
// .setRelativeUrl('v1/upload/process-asset-manually');
if (feId)
request.setUrlParam('feId', feId);
request.execute();
};
this.setDefaultConfig({ manualProcessTriggering: false });
}
__onMessageReceived(notification) {
if (notification.topic !== shared_1.PushKey_FileUploaded)
return;
const data = notification.message;
if (!data)
return this.logError('file upload push without data');
const feId = data.asset.feId;
if (!feId)
return this.logError('file upload push without feId');
this.setFileInfo(feId, data);
}
init() {
if (this.config.uploadQueueParallelCount)
this.uploadQueue.setParallelCount(this.config.uploadQueueParallelCount);
}
getFileInfo(id, key) {
return this.files[id] && this.files[id][key];
}
getFullFileInfo(id) {
if (!id)
return undefined;
return this.files[id];
}
setFileInfo(feId, values) {
const fileInfo = this.files[feId];
if (!fileInfo)
return this.logError(`file upload push received, but no file info exists for ${feId}`);
(0, ts_common_1._keys)(values).forEach(key => fileInfo[key] = values[key]);
this.dispatchFileStatusChange(feId);
}
dispatchFileStatusChange(id) {
this.dispatch_fileStatusChange.dispatchModule(id);
}
uploadImpl(files) {
var _a, _b;
const body = files.map(fileData => {
const { file } = fileData, fileInfo = __rest(fileData, ["file"]);
this.files[fileInfo.feId] = {
file,
status: shared_1.FileStatus.ObtainingUrl,
name: fileData.name
};
return fileInfo;
});
(_b = (_a = this.vv1).getUploadUrl) === null || _b === void 0 ? void 0 : _b.call(_a, body).execute(async (response) => {
body.forEach(f => this.setFileInfo(f.feId, { status: shared_1.FileStatus.UrlObtained }));
if (!response)
return;
// Not a relevant await but still...
await this.uploadFiles(response);
});
return body;
}
}
exports.ModuleBase_AssetUploader = ModuleBase_AssetUploader;