@stemy/backend 2.7.2 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import { dirname, basename, join, resolve } from 'path';
2
2
  import { json } from 'body-parser';
3
3
  import { sign, verify } from 'jsonwebtoken';
4
4
  import { injectable, scoped, Lifecycle, injectAll, singleton, inject, isFactoryProvider, container } from 'tsyringe';
5
- import { createParamDecorator, BadRequestError, HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Get, Param, QueryParams, QueryParam, Res, Controller, Body, CurrentUser, Middleware, useContainer, useExpressServer } from 'routing-controllers';
5
+ import { createParamDecorator, BadRequestError, HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Body, Get, Param, QueryParams, QueryParam, Res, Controller, CurrentUser, Middleware, useContainer, useExpressServer } from 'routing-controllers';
6
6
  import { OnMessage, ConnectedSocket, MessageBody, SocketController, Middleware as Middleware$1, useContainer as useContainer$1, useSocketServer } from 'socket-controllers';
7
7
  import { routingControllersToSpec } from 'routing-controllers-openapi';
8
8
  import { defaultMetadataStorage } from 'class-transformer/storage';
@@ -20,6 +20,7 @@ import { ObjectId } from 'bson';
20
20
  import fontKit_ from 'fontkit';
21
21
  import { fromBuffer, fromStream } from 'file-type';
22
22
  import sharp_ from 'sharp';
23
+ import axios from 'axios';
23
24
  import { GridFSBucket } from 'mongodb';
24
25
  import dotenv from 'dotenv';
25
26
  import { Queue, Worker, Scheduler } from 'node-resque';
@@ -32,11 +33,10 @@ import socket_io from 'socket.io';
32
33
  import { v4 } from 'uuid';
33
34
  import { createTransport } from 'nodemailer';
34
35
  import * as Handlebars from 'handlebars';
35
- import axios from 'axios';
36
36
  import { compare } from 'bcrypt';
37
37
  import moment from 'moment';
38
38
 
39
- var __awaiter$u = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
39
+ var __awaiter$v = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
40
40
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
41
41
  return new (P || (P = Promise))(function (resolve, reject) {
42
42
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -238,7 +238,7 @@ function hydratePopulated(modelType, json) {
238
238
  return object;
239
239
  }
240
240
  function paginateAggregations(model, aggregations, params, metaProjection = {}) {
241
- return __awaiter$u(this, void 0, void 0, function* () {
241
+ return __awaiter$v(this, void 0, void 0, function* () {
242
242
  const sortField = !isString(params.sort) || !params.sort ? null : (params.sort.startsWith("-") ? params.sort.substr(1) : params.sort);
243
243
  const sortAggregation = !sortField ? [] : [{
244
244
  $sort: { [sortField]: sortField == params.sort ? 1 : -1 }
@@ -337,7 +337,7 @@ function readFile(path) {
337
337
  });
338
338
  }
339
339
  function readAndDeleteFile(path, timeout = 5000) {
340
- return __awaiter$u(this, void 0, void 0, function* () {
340
+ return __awaiter$v(this, void 0, void 0, function* () {
341
341
  const data = yield readFile(path);
342
342
  setTimeout(() => {
343
343
  unlink(path, () => {
@@ -347,7 +347,7 @@ function readAndDeleteFile(path, timeout = 5000) {
347
347
  });
348
348
  }
349
349
  function writeFile(path, data) {
350
- return __awaiter$u(this, void 0, void 0, function* () {
350
+ return __awaiter$v(this, void 0, void 0, function* () {
351
351
  yield mkdirRecursive(dirname(path));
352
352
  return new Promise((res, rej) => {
353
353
  writeFile$1(path, data, err => {
@@ -426,7 +426,7 @@ function ResolveEntity(model, extraCheck) {
426
426
  const paramName = modelName.toLowerCase();
427
427
  return createParamDecorator({
428
428
  required: false,
429
- value: (action) => __awaiter$u(this, void 0, void 0, function* () {
429
+ value: (action) => __awaiter$v(this, void 0, void 0, function* () {
430
430
  const req = action.request;
431
431
  const token = req.header(`x-${paramName}-token`);
432
432
  const id = req.params[`${paramName}Id`];
@@ -750,7 +750,7 @@ var __decorate$w = (this && this.__decorate) || function (decorators, target, ke
750
750
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
751
751
  return c > 3 && r && Object.defineProperty(target, key, r), r;
752
752
  };
753
- var __awaiter$t = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
753
+ var __awaiter$u = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
754
754
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
755
755
  return new (P || (P = Promise))(function (resolve, reject) {
756
756
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -775,7 +775,7 @@ const fontProps = [
775
775
  ];
776
776
  let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
777
777
  static getMimeType(buffer, mimeType) {
778
- return __awaiter$t(this, void 0, void 0, function* () {
778
+ return __awaiter$u(this, void 0, void 0, function* () {
779
779
  try {
780
780
  mimeType = (yield fromBuffer(buffer)).mime;
781
781
  }
@@ -807,7 +807,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
807
807
  return imageTypes.indexOf(contentType) >= 0;
808
808
  }
809
809
  static copyImageMeta(buffer, metadata) {
810
- return __awaiter$t(this, void 0, void 0, function* () {
810
+ return __awaiter$u(this, void 0, void 0, function* () {
811
811
  const output = yield sharp$3(buffer).rotate().toBuffer({ resolveWithObject: true });
812
812
  Object.assign(metadata, output.info);
813
813
  return output.data;
@@ -824,7 +824,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
824
824
  });
825
825
  }
826
826
  process(buffer, metadata, contentType) {
827
- return __awaiter$t(this, void 0, void 0, function* () {
827
+ return __awaiter$u(this, void 0, void 0, function* () {
828
828
  if (AssetProcessor_1.isImage(contentType)) {
829
829
  buffer = yield AssetProcessor_1.copyImageMeta(buffer, metadata);
830
830
  }
@@ -899,7 +899,7 @@ var __decorate$u = (this && this.__decorate) || function (decorators, target, ke
899
899
  var __metadata$o = (this && this.__metadata) || function (k, v) {
900
900
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
901
901
  };
902
- var __awaiter$s = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
902
+ var __awaiter$t = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
903
903
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
904
904
  return new (P || (P = Promise))(function (resolve, reject) {
905
905
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -925,7 +925,7 @@ let MongoConnector = class MongoConnector {
925
925
  return this.fsBucket;
926
926
  }
927
927
  connect() {
928
- return __awaiter$s(this, void 0, void 0, function* () {
928
+ return __awaiter$t(this, void 0, void 0, function* () {
929
929
  if (this.db)
930
930
  return this.db;
931
931
  this.conn = (yield connect(this.configuration.resolve("mongoUri"), {
@@ -946,6 +946,43 @@ MongoConnector = __decorate$u([
946
946
  __metadata$o("design:paramtypes", [Configuration])
947
947
  ], MongoConnector);
948
948
 
949
+ var __awaiter$s = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
950
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
951
+ return new (P || (P = Promise))(function (resolve, reject) {
952
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
953
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
954
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
955
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
956
+ });
957
+ };
958
+ class BaseEntity {
959
+ constructor(mId, data, collection) {
960
+ this.mId = mId;
961
+ this.data = data;
962
+ this.collection = collection;
963
+ }
964
+ get id() {
965
+ return this.mId.toHexString();
966
+ }
967
+ save() {
968
+ return this.collection.updateOne({ _id: this.mId }, { $set: this.toJSON() });
969
+ }
970
+ load() {
971
+ return __awaiter$s(this, void 0, void 0, function* () {
972
+ const res = yield this.collection.findOne({ _id: this.mId });
973
+ this.deleted = !res;
974
+ this.data = res || {};
975
+ return this;
976
+ });
977
+ }
978
+ toJSON() {
979
+ const ret = Object.assign({}, this.data);
980
+ delete ret._id;
981
+ ret.id = this.id;
982
+ return ret;
983
+ }
984
+ }
985
+
949
986
  var __awaiter$r = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
950
987
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
951
988
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -962,14 +999,10 @@ const cropInterface = {
962
999
  w: "number",
963
1000
  h: "number"
964
1001
  };
965
- class Asset {
966
- constructor(fileId, filename, contentType, metadata, bucket, collection) {
967
- this.fileId = fileId;
968
- this.filename = filename;
969
- this.contentType = contentType;
970
- this.metadata = metadata;
1002
+ class Asset extends BaseEntity {
1003
+ constructor(id, data, collection, bucket) {
1004
+ super(id, data, collection);
971
1005
  this.bucket = bucket;
972
- this.collection = collection;
973
1006
  }
974
1007
  static toCropRegion(cropInfo) {
975
1008
  let crop = cropInfo;
@@ -993,20 +1026,22 @@ class Asset {
993
1026
  static toImage(stream, meta, params) {
994
1027
  return __awaiter$r(this, void 0, void 0, function* () {
995
1028
  params = params || {};
996
- if (Object.keys(params).length == 0)
1029
+ // Get default crop info
1030
+ const crop = Asset.toCropRegion(meta.crop);
1031
+ // Return back the stream if there is no params and no default crop exists
1032
+ if (Object.keys(params).length == 0 && !crop)
997
1033
  return stream;
998
- let buffer = yield streamToBuffer(stream);
999
1034
  // Parse params
1000
1035
  params.rotation = isNaN(params.rotation) ? 0 : Math.round(params.rotation / 90) * 90;
1001
- params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : params.canvasScaleX;
1002
- params.canvasScaleY = isNaN(params.canvasScaleY) ? 1 : params.canvasScaleY;
1003
- params.scaleX = isNaN(params.scaleX) ? 1 : params.scaleX;
1004
- params.scaleY = isNaN(params.scaleY) ? 1 : params.scaleY;
1036
+ params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : Number(params.canvasScaleX);
1037
+ params.canvasScaleY = isNaN(params.canvasScaleY) ? 1 : Number(params.canvasScaleY);
1038
+ params.scaleX = isNaN(params.scaleX) ? 1 : Number(params.scaleX);
1039
+ params.scaleY = isNaN(params.scaleY) ? 1 : Number(params.scaleY);
1005
1040
  params.crop = isBoolean(params.crop) ? params.crop : params.crop == "true";
1006
1041
  // Try to modify image
1042
+ let buffer = yield streamToBuffer(stream);
1007
1043
  try {
1008
1044
  // Get crop info
1009
- const crop = Asset.toCropRegion(meta.crop);
1010
1045
  const cropBefore = Asset.toCropRegion(params.cropBefore || (params.crop ? meta.cropBefore : null));
1011
1046
  const cropAfter = Asset.toCropRegion(params.cropAfter || (params.crop ? meta.cropAfter : null));
1012
1047
  // Get metadata
@@ -1062,15 +1097,21 @@ class Asset {
1062
1097
  }
1063
1098
  });
1064
1099
  }
1065
- get id() {
1066
- return this.fileId.toHexString();
1100
+ get filename() {
1101
+ return this.data.filename;
1102
+ }
1103
+ get contentType() {
1104
+ return this.data.contentType;
1105
+ }
1106
+ get metadata() {
1107
+ return this.data.metadata;
1067
1108
  }
1068
1109
  get stream() {
1069
- return this.bucket.openDownloadStream(this.fileId);
1110
+ return this.bucket.openDownloadStream(this.mId);
1070
1111
  }
1071
1112
  unlink() {
1072
1113
  return __awaiter$r(this, void 0, void 0, function* () {
1073
- return deleteFromBucket(this.bucket, this.fileId);
1114
+ return deleteFromBucket(this.bucket, this.mId);
1074
1115
  });
1075
1116
  }
1076
1117
  getBuffer() {
@@ -1084,7 +1125,7 @@ class Asset {
1084
1125
  : metadata.downloadCount + 1;
1085
1126
  metadata.firstDownload = metadata.firstDownload || new Date();
1086
1127
  metadata.lastDownload = new Date();
1087
- yield this.collection.updateOne({ _id: this.fileId }, { $set: { metadata } });
1128
+ yield this.collection.updateOne({ _id: this.mId }, { $set: { metadata } });
1088
1129
  return this.stream;
1089
1130
  });
1090
1131
  }
@@ -1098,14 +1139,6 @@ class Asset {
1098
1139
  return Asset.toImage(yield this.download(metadata), this.metadata, params);
1099
1140
  });
1100
1141
  }
1101
- toJSON() {
1102
- return {
1103
- id: this.id,
1104
- filename: this.filename,
1105
- contentType: this.contentType,
1106
- metadata: this.metadata
1107
- };
1108
- }
1109
1142
  }
1110
1143
 
1111
1144
  var __decorate$t = (this && this.__decorate) || function (decorators, target, key, desc) {
@@ -1166,8 +1199,12 @@ let Assets = class Assets {
1166
1199
  reject(error.message || error);
1167
1200
  })
1168
1201
  .on("finish", () => {
1169
- const asset = new Asset(uploaderStream.id, metadata.filename, contentType, metadata, this.bucket, this.collection);
1170
- this.collection.updateOne({ _id: uploaderStream.id }, { $set: asset.toJSON() }).then(() => {
1202
+ const asset = new Asset(uploaderStream.id, {
1203
+ filename: metadata.filename,
1204
+ contentType,
1205
+ metadata
1206
+ }, this.collection, this.bucket);
1207
+ asset.save().then(() => {
1171
1208
  resolve(asset);
1172
1209
  }, error => {
1173
1210
  reject(error.message || error);
@@ -1184,6 +1221,12 @@ let Assets = class Assets {
1184
1221
  return this.write(bufferToStream(buffer), contentType, metadata);
1185
1222
  });
1186
1223
  }
1224
+ writeUrl(url, metadata = null) {
1225
+ return __awaiter$q(this, void 0, void 0, function* () {
1226
+ const buffer = (yield axios({ url, responseType: "arraybuffer" })).data;
1227
+ return this.writeBuffer(buffer, metadata);
1228
+ });
1229
+ }
1187
1230
  read(id) {
1188
1231
  return __awaiter$q(this, void 0, void 0, function* () {
1189
1232
  return this.find({ _id: new ObjectId(id) });
@@ -1192,7 +1235,20 @@ let Assets = class Assets {
1192
1235
  find(where) {
1193
1236
  return __awaiter$q(this, void 0, void 0, function* () {
1194
1237
  const data = yield this.collection.findOne(where);
1195
- return !data ? null : new Asset(data._id, data.filename, data.contentType, data.metadata, this.bucket, this.collection);
1238
+ return !data ? null : new Asset(data._id, data, this.collection, this.bucket);
1239
+ });
1240
+ }
1241
+ findMany(where) {
1242
+ return __awaiter$q(this, void 0, void 0, function* () {
1243
+ const cursor = this.collection.find(where);
1244
+ const items = (yield cursor.toArray()) || [];
1245
+ const result = [];
1246
+ for (let item of items) {
1247
+ if (!item)
1248
+ continue;
1249
+ result.push(new Asset(item._id, item, this.collection, this.bucket));
1250
+ }
1251
+ return result;
1196
1252
  });
1197
1253
  }
1198
1254
  unlink(id) {
@@ -1219,52 +1275,61 @@ var __awaiter$p = (this && this.__awaiter) || function (thisArg, _arguments, P,
1219
1275
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1220
1276
  });
1221
1277
  };
1222
- class LazyAsset {
1223
- constructor(lazyId, jobName, jobParams, jobQue, mProgressId, mAssetId, assets, progresses, jobMan, collection) {
1224
- this.lazyId = lazyId;
1225
- this.jobName = jobName;
1226
- this.jobParams = jobParams;
1227
- this.jobQue = jobQue;
1228
- this.mProgressId = mProgressId;
1229
- this.mAssetId = mAssetId;
1278
+ class LazyAsset extends BaseEntity {
1279
+ constructor(id, data, collection, assets, progresses, jobMan) {
1280
+ super(id, data, collection);
1230
1281
  this.assets = assets;
1231
1282
  this.progresses = progresses;
1232
1283
  this.jobMan = jobMan;
1233
- this.collection = collection;
1234
1284
  }
1235
- get id() {
1236
- return this.lazyId.toHexString();
1285
+ get jobName() {
1286
+ return this.data.jobName;
1287
+ }
1288
+ get jobParams() {
1289
+ return this.data.jobParams;
1290
+ }
1291
+ get jobQue() {
1292
+ return this.data.jobQue;
1237
1293
  }
1238
1294
  get progressId() {
1239
- return this.mProgressId;
1295
+ return this.data.progressId;
1240
1296
  }
1241
1297
  get assetId() {
1242
- return this.mAssetId;
1298
+ return this.data.assetId;
1243
1299
  }
1244
1300
  unlink() {
1245
1301
  return __awaiter$p(this, void 0, void 0, function* () {
1246
- yield this.collection.deleteOne({ _id: this.lazyId });
1247
- return deleteFromBucket(this.assets.bucket, new ObjectId(this.mAssetId));
1302
+ yield this.load();
1303
+ if (!this.progressId) {
1304
+ yield this.collection.deleteOne({ _id: this.mId });
1305
+ }
1306
+ return deleteFromBucket(this.assets.bucket, new ObjectId(this.assetId));
1248
1307
  });
1249
1308
  }
1250
1309
  startWorking() {
1251
- if (this.mProgressId)
1252
- return;
1253
- this.startWorkingOnAsset().then(() => {
1254
- console.log(`Started working on lazy asset: ${this.id}`);
1255
- }).catch(reason => {
1256
- console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1310
+ this.load().then(() => {
1311
+ if (this.deleted)
1312
+ return;
1313
+ const progressPromise = !this.progressId ? Promise.resolve(null) : this.progresses.get(this.progressId).then(p => p.cancel());
1314
+ progressPromise.then(() => {
1315
+ this.startWorkingOnAsset().then(() => {
1316
+ console.log(`Started working on lazy asset: ${this.id}`);
1317
+ }).catch(reason => {
1318
+ console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1319
+ });
1320
+ });
1257
1321
  });
1258
1322
  }
1259
1323
  loadAsset() {
1260
1324
  return __awaiter$p(this, void 0, void 0, function* () {
1261
- if (this.mAssetId) {
1262
- return this.assets.read(this.mAssetId);
1325
+ yield this.load();
1326
+ if (this.deleted)
1327
+ return null;
1328
+ if (this.assetId) {
1329
+ return this.assets.read(this.assetId);
1263
1330
  }
1264
- if (this.mProgressId) {
1265
- yield this.progresses.waitToFinish(this.mProgressId);
1266
- const data = yield this.collection.findOne({ _id: this.lazyId });
1267
- this.mAssetId = data.assetId;
1331
+ if (this.progressId) {
1332
+ yield this.progresses.waitToFinish(this.progressId);
1268
1333
  return this.loadAsset();
1269
1334
  }
1270
1335
  yield this.startWorkingOnAsset();
@@ -1273,30 +1338,17 @@ class LazyAsset {
1273
1338
  }
1274
1339
  writeAsset(asset) {
1275
1340
  return __awaiter$p(this, void 0, void 0, function* () {
1276
- this.mAssetId = asset.id;
1341
+ this.data.assetId = asset.id;
1277
1342
  yield this.save();
1278
1343
  return asset;
1279
1344
  });
1280
1345
  }
1281
- save() {
1282
- return this.collection.updateOne({ _id: this.lazyId }, { $set: this.toJSON() });
1283
- }
1284
- toJSON() {
1285
- return {
1286
- id: this.id,
1287
- jobName: this.jobName,
1288
- jobParams: this.jobParams,
1289
- jobQue: this.jobQue,
1290
- progressId: this.progressId,
1291
- assetId: this.assetId,
1292
- };
1293
- }
1294
1346
  startWorkingOnAsset() {
1295
1347
  return __awaiter$p(this, void 0, void 0, function* () {
1296
- const progress = yield this.progresses.create();
1297
- this.mProgressId = progress.id;
1348
+ const { id } = yield this.progresses.create();
1349
+ this.data.progressId = id;
1298
1350
  yield this.save();
1299
- yield this.jobMan.enqueueWithName(this.jobName, Object.assign(Object.assign({}, this.jobParams), { lazyId: this.id }));
1351
+ yield this.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id }));
1300
1352
  });
1301
1353
  }
1302
1354
  }
@@ -1505,36 +1557,31 @@ var __awaiter$n = (this && this.__awaiter) || function (thisArg, _arguments, P,
1505
1557
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1506
1558
  });
1507
1559
  };
1508
- class Progress {
1509
- constructor(progressId, mCurrent, mMax, mMessage, mError, client, collection) {
1510
- this.progressId = progressId;
1511
- this.mCurrent = mCurrent;
1512
- this.mMax = mMax;
1513
- this.mMessage = mMessage;
1514
- this.mError = mError;
1560
+ class Progress extends BaseEntity {
1561
+ constructor(id, data, collection, client) {
1562
+ super(id, data, collection);
1515
1563
  this.client = client;
1516
- this.collection = collection;
1517
- }
1518
- get id() {
1519
- return this.progressId.toHexString();
1520
1564
  }
1521
1565
  get current() {
1522
- return this.mCurrent;
1566
+ return this.data.current;
1523
1567
  }
1524
1568
  get max() {
1525
- return this.mMax;
1569
+ return this.data.max;
1526
1570
  }
1527
1571
  get message() {
1528
- return this.mMessage;
1572
+ return this.data.message;
1529
1573
  }
1530
1574
  get error() {
1531
- return this.mError;
1575
+ return this.data.error;
1576
+ }
1577
+ get canceled() {
1578
+ return this.data.canceled;
1532
1579
  }
1533
1580
  get percent() {
1534
- return this.mMax > 0 ? Math.round(this.mCurrent / this.mMax * 100) : 0;
1581
+ return this.max > 0 ? Math.round(this.current / this.max * 100) : 0;
1535
1582
  }
1536
1583
  get remaining() {
1537
- return this.mMax > 0 ? this.mMax - this.mCurrent : 0;
1584
+ return this.max > 0 ? this.max - this.current : 0;
1538
1585
  }
1539
1586
  createSubProgress(progressValue, max, message) {
1540
1587
  return __awaiter$n(this, void 0, void 0, function* () {
@@ -1542,10 +1589,10 @@ class Progress {
1542
1589
  yield this.advance(progressValue);
1543
1590
  }
1544
1591
  if (message !== null) {
1545
- this.mMessage = message;
1592
+ this.data.message = message;
1546
1593
  yield this.save();
1547
1594
  }
1548
- return new SubProgress(this, this.mCurrent, progressValue, Math.max(max, 1));
1595
+ return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1549
1596
  });
1550
1597
  }
1551
1598
  setMax(max) {
@@ -1553,13 +1600,19 @@ class Progress {
1553
1600
  if (isNaN(max) || max <= 0) {
1554
1601
  throw "Max progress value must be bigger than zero";
1555
1602
  }
1556
- this.mMax = max;
1603
+ this.data.max = max;
1604
+ yield this.save();
1605
+ });
1606
+ }
1607
+ setMessage(message) {
1608
+ return __awaiter$n(this, void 0, void 0, function* () {
1609
+ this.data.message = message;
1557
1610
  yield this.save();
1558
1611
  });
1559
1612
  }
1560
1613
  setError(error) {
1561
1614
  return __awaiter$n(this, void 0, void 0, function* () {
1562
- this.mError = error;
1615
+ this.data.error = error;
1563
1616
  yield this.save();
1564
1617
  });
1565
1618
  }
@@ -1568,63 +1621,60 @@ class Progress {
1568
1621
  if (isNaN(value) || value <= 0) {
1569
1622
  throw "Advance value must be bigger than zero";
1570
1623
  }
1571
- this.mCurrent = Math.min(this.mMax, this.mCurrent + value);
1624
+ yield this.load();
1625
+ if (this.deleted || this.canceled)
1626
+ return null;
1627
+ this.data.current = Math.min(this.max, this.current + value);
1572
1628
  yield this.save();
1573
1629
  if (!this.client)
1574
1630
  return;
1575
1631
  this.client.emit("background-progress", this.id);
1576
1632
  });
1577
1633
  }
1578
- toJSON() {
1579
- return {
1580
- id: this.id,
1581
- current: this.current,
1582
- max: this.max,
1583
- message: this.message,
1584
- error: this.error
1585
- };
1586
- }
1587
- save() {
1588
- return this.collection.updateOne({ _id: this.progressId }, { $set: this.toJSON() });
1634
+ cancel() {
1635
+ return __awaiter$n(this, void 0, void 0, function* () {
1636
+ this.data.canceled = true;
1637
+ yield this.save();
1638
+ });
1589
1639
  }
1590
1640
  }
1591
1641
  class SubProgress {
1592
- constructor(parent, progressFrom, progressValue, max = 100) {
1642
+ constructor(parent, progressFrom, progressValue, mMax = 100) {
1593
1643
  this.parent = parent;
1594
1644
  this.progressFrom = progressFrom;
1595
1645
  this.progressValue = progressValue;
1596
- this.max = max;
1646
+ this.mMax = mMax;
1597
1647
  if (progressFrom < 0) {
1598
1648
  throw "Progress from must be bigger than or zero";
1599
1649
  }
1600
1650
  if (progressValue <= 0) {
1601
1651
  throw "Progress value must be bigger than zero";
1602
1652
  }
1603
- this.currentValue = 0;
1653
+ this.mCurrent = 0;
1604
1654
  }
1605
1655
  get id() {
1606
1656
  return this.parent.id;
1607
1657
  }
1658
+ get current() {
1659
+ return this.mCurrent;
1660
+ }
1661
+ get max() {
1662
+ return this.mMax;
1663
+ }
1608
1664
  get message() {
1609
1665
  return this.parent.message;
1610
1666
  }
1611
- set message(value) {
1612
- this.parent.message = value;
1613
- }
1614
1667
  get error() {
1615
1668
  return this.parent.error;
1616
1669
  }
1617
- set error(value) {
1618
- this.parent.error = value;
1619
- }
1620
1670
  get percent() {
1621
1671
  return this.parent.percent;
1622
1672
  }
1623
- get current() {
1624
- return this.currentValue;
1625
- }
1626
1673
  get remaining() {
1627
- return this.max - this.currentValue;
1674
+ return this.max - this.mCurrent;
1675
+ }
1676
+ get canceled() {
1677
+ return !this.parent || this.parent.canceled;
1628
1678
  }
1629
1679
  createSubProgress(progressValue, max, message) {
1630
1680
  return __awaiter$n(this, void 0, void 0, function* () {
@@ -1632,8 +1682,7 @@ class SubProgress {
1632
1682
  yield this.advance(progressValue);
1633
1683
  }
1634
1684
  if (message !== null) {
1635
- this.message = message;
1636
- yield this.parent.save();
1685
+ yield this.setMessage(message);
1637
1686
  }
1638
1687
  return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1639
1688
  });
@@ -1643,14 +1692,22 @@ class SubProgress {
1643
1692
  if (isNaN(max) || max <= 0) {
1644
1693
  throw "Max progress value must be bigger than zero";
1645
1694
  }
1646
- this.max = max;
1695
+ this.mMax = max;
1647
1696
  yield this.save();
1648
1697
  });
1649
1698
  }
1699
+ setMessage(message) {
1700
+ return __awaiter$n(this, void 0, void 0, function* () {
1701
+ if (!this.parent)
1702
+ return null;
1703
+ yield this.parent.setMessage(message);
1704
+ });
1705
+ }
1650
1706
  setError(error) {
1651
1707
  return __awaiter$n(this, void 0, void 0, function* () {
1652
- this.error = error || null;
1653
- yield this.save();
1708
+ if (!this.parent)
1709
+ return null;
1710
+ yield this.parent.setError(error);
1654
1711
  });
1655
1712
  }
1656
1713
  advance(value = 1) {
@@ -1658,13 +1715,20 @@ class SubProgress {
1658
1715
  if (isNaN(value) || value <= 0) {
1659
1716
  throw "Advance value must be bigger than zero";
1660
1717
  }
1661
- this.currentValue = Math.min(this.max, this.currentValue + value);
1718
+ this.mCurrent = Math.min(this.max, this.mCurrent + value);
1662
1719
  yield this.save();
1663
1720
  });
1664
1721
  }
1722
+ cancel() {
1723
+ return __awaiter$n(this, void 0, void 0, function* () {
1724
+ if (!this.parent)
1725
+ return null;
1726
+ yield this.parent.cancel();
1727
+ });
1728
+ }
1665
1729
  save() {
1666
1730
  return __awaiter$n(this, void 0, void 0, function* () {
1667
- const ratio = this.max > 0 ? this.currentValue / this.max : 0;
1731
+ const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
1668
1732
  const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
1669
1733
  const current = this.parent.current;
1670
1734
  if (newProgress <= current)
@@ -1672,6 +1736,11 @@ class SubProgress {
1672
1736
  yield this.parent.advance(newProgress);
1673
1737
  });
1674
1738
  }
1739
+ load() {
1740
+ return __awaiter$n(this, void 0, void 0, function* () {
1741
+ return null;
1742
+ });
1743
+ }
1675
1744
  toJSON() {
1676
1745
  return this.parent.toJSON();
1677
1746
  }
@@ -1732,7 +1801,7 @@ let Progresses = class Progresses {
1732
1801
  find(where) {
1733
1802
  return __awaiter$m(this, void 0, void 0, function* () {
1734
1803
  const data = yield this.collection.findOne(where);
1735
- return !data ? null : new Progress(data._id, data.current, data.max, data.message, data.error, this.client, this.collection);
1804
+ return !data ? null : new Progress(data._id, data, this.collection, this.client);
1736
1805
  });
1737
1806
  }
1738
1807
  create(max = 100) {
@@ -1740,11 +1809,15 @@ let Progresses = class Progresses {
1740
1809
  if (isNaN(max) || max <= 0) {
1741
1810
  throw "Max progress value must be bigger than zero";
1742
1811
  }
1743
- const res = yield this.collection.insertOne({
1812
+ const data = {
1744
1813
  current: 0,
1745
- max
1746
- });
1747
- return new Progress(res.insertedId, 0, max, "", "", this.client, this.collection);
1814
+ max: max,
1815
+ message: "",
1816
+ error: "",
1817
+ canceled: false
1818
+ };
1819
+ const res = yield this.collection.insertOne(data);
1820
+ return new Progress(res.insertedId, data, this.collection, this.client);
1748
1821
  });
1749
1822
  }
1750
1823
  remove(id) {
@@ -1789,12 +1862,16 @@ let LazyAssets = class LazyAssets {
1789
1862
  create(jobType, jobParams = {}, jobQue = "main") {
1790
1863
  return __awaiter$l(this, void 0, void 0, function* () {
1791
1864
  const jobName = this.jobMan.tryResolve(jobType, Object.assign(Object.assign({}, jobParams), { lazyId: "" }));
1792
- const res = yield this.collection.insertOne({
1865
+ const data = {
1793
1866
  jobName,
1794
1867
  jobParams,
1795
1868
  jobQue
1796
- });
1797
- return new LazyAsset(res.insertedId, jobName, jobParams, jobQue, null, null, this.assets, this.progresses, this.jobMan, this.collection);
1869
+ };
1870
+ const existingAsset = yield this.find(data);
1871
+ if (existingAsset)
1872
+ return existingAsset;
1873
+ const res = yield this.collection.insertOne(data);
1874
+ return new LazyAsset(res.insertedId, data, this.collection, this.assets, this.progresses, this.jobMan);
1798
1875
  });
1799
1876
  }
1800
1877
  read(id) {
@@ -1807,7 +1884,7 @@ let LazyAssets = class LazyAssets {
1807
1884
  const data = yield this.collection.findOne(where);
1808
1885
  return !data
1809
1886
  ? null
1810
- : new LazyAsset(data._id, data.jobName, data.jobParams, data.jobQue, data.progressId, data.assetId, this.assets, this.progresses, this.jobMan, this.collection);
1887
+ : new LazyAsset(data._id, data, this.collection, this.assets, this.progresses, this.jobMan);
1811
1888
  });
1812
1889
  }
1813
1890
  unlink(id) {
@@ -2769,6 +2846,18 @@ let AssetsController = class AssetsController {
2769
2846
  }
2770
2847
  });
2771
2848
  }
2849
+ uploadUrl(body) {
2850
+ return __awaiter$7(this, void 0, void 0, function* () {
2851
+ try {
2852
+ const asset = yield this.assets.writeUrl(body.url, body);
2853
+ return asset.toJSON();
2854
+ }
2855
+ catch (e) {
2856
+ const msg = (e === null || e === void 0 ? void 0 : e.message) || e || "Unknown error";
2857
+ throw new HttpError(400, `Asset can't be uploaded.\n${msg}`);
2858
+ }
2859
+ });
2860
+ }
2772
2861
  getImageRotation(id, params, rotation = 0) {
2773
2862
  var _a;
2774
2863
  return __awaiter$7(this, void 0, void 0, function* () {
@@ -2814,6 +2903,14 @@ __decorate$a([
2814
2903
  __metadata$7("design:paramtypes", [Object]),
2815
2904
  __metadata$7("design:returntype", Promise)
2816
2905
  ], AssetsController.prototype, "upload", null);
2906
+ __decorate$a([
2907
+ Authorized(),
2908
+ Post("url"),
2909
+ __param$5(0, Body()),
2910
+ __metadata$7("design:type", Function),
2911
+ __metadata$7("design:paramtypes", [Object]),
2912
+ __metadata$7("design:returntype", Promise)
2913
+ ], AssetsController.prototype, "uploadUrl", null);
2817
2914
  __decorate$a([
2818
2915
  Get("/image/:id/:rotation"),
2819
2916
  __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Param("rotation")),
@@ -3499,9 +3596,14 @@ class LazyAssetGenerator {
3499
3596
  process() {
3500
3597
  return __awaiter$1(this, void 0, void 0, function* () {
3501
3598
  const lazyAsset = yield this.lazyAssets.read(this.lazyId);
3502
- const progress = yield this.progresses.get(lazyAsset.progressId);
3599
+ let progress = yield this.progresses.get(lazyAsset.progressId);
3600
+ if (!progress || progress.canceled)
3601
+ return null;
3503
3602
  try {
3504
3603
  const asset = yield this.generate(progress);
3604
+ progress = yield progress.load();
3605
+ if (!progress || progress.canceled)
3606
+ return null;
3505
3607
  yield lazyAsset.writeAsset(asset);
3506
3608
  }
3507
3609
  catch (e) {