UNPKG

@nu-art/file-upload

Version:

File Uploader - Express & Typescript based backend framework

156 lines (155 loc) 6.74 kB
"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;