@stemy/backend 2.7.3 → 2.8.2

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;
@@ -1064,15 +1097,21 @@ class Asset {
1064
1097
  }
1065
1098
  });
1066
1099
  }
1067
- get id() {
1068
- 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;
1069
1108
  }
1070
1109
  get stream() {
1071
- return this.bucket.openDownloadStream(this.fileId);
1110
+ return this.bucket.openDownloadStream(this.mId);
1072
1111
  }
1073
1112
  unlink() {
1074
1113
  return __awaiter$r(this, void 0, void 0, function* () {
1075
- return deleteFromBucket(this.bucket, this.fileId);
1114
+ return deleteFromBucket(this.bucket, this.mId);
1076
1115
  });
1077
1116
  }
1078
1117
  getBuffer() {
@@ -1086,7 +1125,7 @@ class Asset {
1086
1125
  : metadata.downloadCount + 1;
1087
1126
  metadata.firstDownload = metadata.firstDownload || new Date();
1088
1127
  metadata.lastDownload = new Date();
1089
- yield this.collection.updateOne({ _id: this.fileId }, { $set: { metadata } });
1128
+ yield this.collection.updateOne({ _id: this.mId }, { $set: { metadata } });
1090
1129
  return this.stream;
1091
1130
  });
1092
1131
  }
@@ -1100,14 +1139,6 @@ class Asset {
1100
1139
  return Asset.toImage(yield this.download(metadata), this.metadata, params);
1101
1140
  });
1102
1141
  }
1103
- toJSON() {
1104
- return {
1105
- id: this.id,
1106
- filename: this.filename,
1107
- contentType: this.contentType,
1108
- metadata: this.metadata
1109
- };
1110
- }
1111
1142
  }
1112
1143
 
1113
1144
  var __decorate$t = (this && this.__decorate) || function (decorators, target, key, desc) {
@@ -1168,8 +1199,12 @@ let Assets = class Assets {
1168
1199
  reject(error.message || error);
1169
1200
  })
1170
1201
  .on("finish", () => {
1171
- const asset = new Asset(uploaderStream.id, metadata.filename, contentType, metadata, this.bucket, this.collection);
1172
- 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(() => {
1173
1208
  resolve(asset);
1174
1209
  }, error => {
1175
1210
  reject(error.message || error);
@@ -1186,6 +1221,12 @@ let Assets = class Assets {
1186
1221
  return this.write(bufferToStream(buffer), contentType, metadata);
1187
1222
  });
1188
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
+ }
1189
1230
  read(id) {
1190
1231
  return __awaiter$q(this, void 0, void 0, function* () {
1191
1232
  return this.find({ _id: new ObjectId(id) });
@@ -1194,7 +1235,20 @@ let Assets = class Assets {
1194
1235
  find(where) {
1195
1236
  return __awaiter$q(this, void 0, void 0, function* () {
1196
1237
  const data = yield this.collection.findOne(where);
1197
- 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;
1198
1252
  });
1199
1253
  }
1200
1254
  unlink(id) {
@@ -1221,52 +1275,61 @@ var __awaiter$p = (this && this.__awaiter) || function (thisArg, _arguments, P,
1221
1275
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1222
1276
  });
1223
1277
  };
1224
- class LazyAsset {
1225
- constructor(lazyId, jobName, jobParams, jobQue, mProgressId, mAssetId, assets, progresses, jobMan, collection) {
1226
- this.lazyId = lazyId;
1227
- this.jobName = jobName;
1228
- this.jobParams = jobParams;
1229
- this.jobQue = jobQue;
1230
- this.mProgressId = mProgressId;
1231
- this.mAssetId = mAssetId;
1278
+ class LazyAsset extends BaseEntity {
1279
+ constructor(id, data, collection, assets, progresses, jobMan) {
1280
+ super(id, data, collection);
1232
1281
  this.assets = assets;
1233
1282
  this.progresses = progresses;
1234
1283
  this.jobMan = jobMan;
1235
- this.collection = collection;
1236
1284
  }
1237
- get id() {
1238
- 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;
1239
1293
  }
1240
1294
  get progressId() {
1241
- return this.mProgressId;
1295
+ return this.data.progressId;
1242
1296
  }
1243
1297
  get assetId() {
1244
- return this.mAssetId;
1298
+ return this.data.assetId;
1245
1299
  }
1246
1300
  unlink() {
1247
1301
  return __awaiter$p(this, void 0, void 0, function* () {
1248
- yield this.collection.deleteOne({ _id: this.lazyId });
1249
- 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));
1250
1307
  });
1251
1308
  }
1252
1309
  startWorking() {
1253
- if (this.mProgressId)
1254
- return;
1255
- this.startWorkingOnAsset().then(() => {
1256
- console.log(`Started working on lazy asset: ${this.id}`);
1257
- }).catch(reason => {
1258
- 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
+ });
1259
1321
  });
1260
1322
  }
1261
1323
  loadAsset() {
1262
1324
  return __awaiter$p(this, void 0, void 0, function* () {
1263
- if (this.mAssetId) {
1264
- 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);
1265
1330
  }
1266
- if (this.mProgressId) {
1267
- yield this.progresses.waitToFinish(this.mProgressId);
1268
- const data = yield this.collection.findOne({ _id: this.lazyId });
1269
- this.mAssetId = data.assetId;
1331
+ if (this.progressId) {
1332
+ yield this.progresses.waitToFinish(this.progressId);
1270
1333
  return this.loadAsset();
1271
1334
  }
1272
1335
  yield this.startWorkingOnAsset();
@@ -1275,30 +1338,17 @@ class LazyAsset {
1275
1338
  }
1276
1339
  writeAsset(asset) {
1277
1340
  return __awaiter$p(this, void 0, void 0, function* () {
1278
- this.mAssetId = asset.id;
1341
+ this.data.assetId = asset.id;
1279
1342
  yield this.save();
1280
1343
  return asset;
1281
1344
  });
1282
1345
  }
1283
- save() {
1284
- return this.collection.updateOne({ _id: this.lazyId }, { $set: this.toJSON() });
1285
- }
1286
- toJSON() {
1287
- return {
1288
- id: this.id,
1289
- jobName: this.jobName,
1290
- jobParams: this.jobParams,
1291
- jobQue: this.jobQue,
1292
- progressId: this.progressId,
1293
- assetId: this.assetId,
1294
- };
1295
- }
1296
1346
  startWorkingOnAsset() {
1297
1347
  return __awaiter$p(this, void 0, void 0, function* () {
1298
- const progress = yield this.progresses.create();
1299
- this.mProgressId = progress.id;
1348
+ const { id } = yield this.progresses.create();
1349
+ this.data.progressId = id;
1300
1350
  yield this.save();
1301
- 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 }));
1302
1352
  });
1303
1353
  }
1304
1354
  }
@@ -1507,36 +1557,31 @@ var __awaiter$n = (this && this.__awaiter) || function (thisArg, _arguments, P,
1507
1557
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1508
1558
  });
1509
1559
  };
1510
- class Progress {
1511
- constructor(progressId, mCurrent, mMax, mMessage, mError, client, collection) {
1512
- this.progressId = progressId;
1513
- this.mCurrent = mCurrent;
1514
- this.mMax = mMax;
1515
- this.mMessage = mMessage;
1516
- this.mError = mError;
1560
+ class Progress extends BaseEntity {
1561
+ constructor(id, data, collection, client) {
1562
+ super(id, data, collection);
1517
1563
  this.client = client;
1518
- this.collection = collection;
1519
- }
1520
- get id() {
1521
- return this.progressId.toHexString();
1522
1564
  }
1523
1565
  get current() {
1524
- return this.mCurrent;
1566
+ return this.data.current;
1525
1567
  }
1526
1568
  get max() {
1527
- return this.mMax;
1569
+ return this.data.max;
1528
1570
  }
1529
1571
  get message() {
1530
- return this.mMessage;
1572
+ return this.data.message;
1531
1573
  }
1532
1574
  get error() {
1533
- return this.mError;
1575
+ return this.data.error;
1576
+ }
1577
+ get canceled() {
1578
+ return this.data.canceled;
1534
1579
  }
1535
1580
  get percent() {
1536
- 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;
1537
1582
  }
1538
1583
  get remaining() {
1539
- return this.mMax > 0 ? this.mMax - this.mCurrent : 0;
1584
+ return this.max > 0 ? this.max - this.current : 0;
1540
1585
  }
1541
1586
  createSubProgress(progressValue, max, message) {
1542
1587
  return __awaiter$n(this, void 0, void 0, function* () {
@@ -1544,10 +1589,10 @@ class Progress {
1544
1589
  yield this.advance(progressValue);
1545
1590
  }
1546
1591
  if (message !== null) {
1547
- this.mMessage = message;
1592
+ this.data.message = message;
1548
1593
  yield this.save();
1549
1594
  }
1550
- return new SubProgress(this, this.mCurrent, progressValue, Math.max(max, 1));
1595
+ return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1551
1596
  });
1552
1597
  }
1553
1598
  setMax(max) {
@@ -1555,13 +1600,19 @@ class Progress {
1555
1600
  if (isNaN(max) || max <= 0) {
1556
1601
  throw "Max progress value must be bigger than zero";
1557
1602
  }
1558
- 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;
1559
1610
  yield this.save();
1560
1611
  });
1561
1612
  }
1562
1613
  setError(error) {
1563
1614
  return __awaiter$n(this, void 0, void 0, function* () {
1564
- this.mError = error;
1615
+ this.data.error = error;
1565
1616
  yield this.save();
1566
1617
  });
1567
1618
  }
@@ -1570,63 +1621,60 @@ class Progress {
1570
1621
  if (isNaN(value) || value <= 0) {
1571
1622
  throw "Advance value must be bigger than zero";
1572
1623
  }
1573
- 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);
1574
1628
  yield this.save();
1575
1629
  if (!this.client)
1576
1630
  return;
1577
1631
  this.client.emit("background-progress", this.id);
1578
1632
  });
1579
1633
  }
1580
- toJSON() {
1581
- return {
1582
- id: this.id,
1583
- current: this.current,
1584
- max: this.max,
1585
- message: this.message,
1586
- error: this.error
1587
- };
1588
- }
1589
- save() {
1590
- 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
+ });
1591
1639
  }
1592
1640
  }
1593
1641
  class SubProgress {
1594
- constructor(parent, progressFrom, progressValue, max = 100) {
1642
+ constructor(parent, progressFrom, progressValue, mMax = 100) {
1595
1643
  this.parent = parent;
1596
1644
  this.progressFrom = progressFrom;
1597
1645
  this.progressValue = progressValue;
1598
- this.max = max;
1646
+ this.mMax = mMax;
1599
1647
  if (progressFrom < 0) {
1600
1648
  throw "Progress from must be bigger than or zero";
1601
1649
  }
1602
1650
  if (progressValue <= 0) {
1603
1651
  throw "Progress value must be bigger than zero";
1604
1652
  }
1605
- this.currentValue = 0;
1653
+ this.mCurrent = 0;
1606
1654
  }
1607
1655
  get id() {
1608
1656
  return this.parent.id;
1609
1657
  }
1658
+ get current() {
1659
+ return this.mCurrent;
1660
+ }
1661
+ get max() {
1662
+ return this.mMax;
1663
+ }
1610
1664
  get message() {
1611
1665
  return this.parent.message;
1612
1666
  }
1613
- set message(value) {
1614
- this.parent.message = value;
1615
- }
1616
1667
  get error() {
1617
1668
  return this.parent.error;
1618
1669
  }
1619
- set error(value) {
1620
- this.parent.error = value;
1621
- }
1622
1670
  get percent() {
1623
1671
  return this.parent.percent;
1624
1672
  }
1625
- get current() {
1626
- return this.currentValue;
1627
- }
1628
1673
  get remaining() {
1629
- return this.max - this.currentValue;
1674
+ return this.max - this.mCurrent;
1675
+ }
1676
+ get canceled() {
1677
+ return !this.parent || this.parent.canceled;
1630
1678
  }
1631
1679
  createSubProgress(progressValue, max, message) {
1632
1680
  return __awaiter$n(this, void 0, void 0, function* () {
@@ -1634,8 +1682,7 @@ class SubProgress {
1634
1682
  yield this.advance(progressValue);
1635
1683
  }
1636
1684
  if (message !== null) {
1637
- this.message = message;
1638
- yield this.parent.save();
1685
+ yield this.setMessage(message);
1639
1686
  }
1640
1687
  return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1641
1688
  });
@@ -1645,14 +1692,22 @@ class SubProgress {
1645
1692
  if (isNaN(max) || max <= 0) {
1646
1693
  throw "Max progress value must be bigger than zero";
1647
1694
  }
1648
- this.max = max;
1695
+ this.mMax = max;
1649
1696
  yield this.save();
1650
1697
  });
1651
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
+ }
1652
1706
  setError(error) {
1653
1707
  return __awaiter$n(this, void 0, void 0, function* () {
1654
- this.error = error || null;
1655
- yield this.save();
1708
+ if (!this.parent)
1709
+ return null;
1710
+ yield this.parent.setError(error);
1656
1711
  });
1657
1712
  }
1658
1713
  advance(value = 1) {
@@ -1660,13 +1715,20 @@ class SubProgress {
1660
1715
  if (isNaN(value) || value <= 0) {
1661
1716
  throw "Advance value must be bigger than zero";
1662
1717
  }
1663
- this.currentValue = Math.min(this.max, this.currentValue + value);
1718
+ this.mCurrent = Math.min(this.max, this.mCurrent + value);
1664
1719
  yield this.save();
1665
1720
  });
1666
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
+ }
1667
1729
  save() {
1668
1730
  return __awaiter$n(this, void 0, void 0, function* () {
1669
- const ratio = this.max > 0 ? this.currentValue / this.max : 0;
1731
+ const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
1670
1732
  const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
1671
1733
  const current = this.parent.current;
1672
1734
  if (newProgress <= current)
@@ -1674,6 +1736,11 @@ class SubProgress {
1674
1736
  yield this.parent.advance(newProgress);
1675
1737
  });
1676
1738
  }
1739
+ load() {
1740
+ return __awaiter$n(this, void 0, void 0, function* () {
1741
+ return null;
1742
+ });
1743
+ }
1677
1744
  toJSON() {
1678
1745
  return this.parent.toJSON();
1679
1746
  }
@@ -1734,7 +1801,7 @@ let Progresses = class Progresses {
1734
1801
  find(where) {
1735
1802
  return __awaiter$m(this, void 0, void 0, function* () {
1736
1803
  const data = yield this.collection.findOne(where);
1737
- 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);
1738
1805
  });
1739
1806
  }
1740
1807
  create(max = 100) {
@@ -1742,11 +1809,15 @@ let Progresses = class Progresses {
1742
1809
  if (isNaN(max) || max <= 0) {
1743
1810
  throw "Max progress value must be bigger than zero";
1744
1811
  }
1745
- const res = yield this.collection.insertOne({
1812
+ const data = {
1746
1813
  current: 0,
1747
- max
1748
- });
1749
- 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);
1750
1821
  });
1751
1822
  }
1752
1823
  remove(id) {
@@ -1791,12 +1862,16 @@ let LazyAssets = class LazyAssets {
1791
1862
  create(jobType, jobParams = {}, jobQue = "main") {
1792
1863
  return __awaiter$l(this, void 0, void 0, function* () {
1793
1864
  const jobName = this.jobMan.tryResolve(jobType, Object.assign(Object.assign({}, jobParams), { lazyId: "" }));
1794
- const res = yield this.collection.insertOne({
1865
+ const data = {
1795
1866
  jobName,
1796
1867
  jobParams,
1797
1868
  jobQue
1798
- });
1799
- 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);
1800
1875
  });
1801
1876
  }
1802
1877
  read(id) {
@@ -1809,7 +1884,7 @@ let LazyAssets = class LazyAssets {
1809
1884
  const data = yield this.collection.findOne(where);
1810
1885
  return !data
1811
1886
  ? null
1812
- : 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);
1813
1888
  });
1814
1889
  }
1815
1890
  unlink(id) {
@@ -2771,6 +2846,18 @@ let AssetsController = class AssetsController {
2771
2846
  }
2772
2847
  });
2773
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
+ }
2774
2861
  getImageRotation(id, params, rotation = 0) {
2775
2862
  var _a;
2776
2863
  return __awaiter$7(this, void 0, void 0, function* () {
@@ -2816,6 +2903,14 @@ __decorate$a([
2816
2903
  __metadata$7("design:paramtypes", [Object]),
2817
2904
  __metadata$7("design:returntype", Promise)
2818
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);
2819
2914
  __decorate$a([
2820
2915
  Get("/image/:id/:rotation"),
2821
2916
  __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Param("rotation")),
@@ -3259,8 +3354,9 @@ CompressionMiddleware = __decorate([
3259
3354
  ], CompressionMiddleware);
3260
3355
 
3261
3356
  class Tree {
3262
- constructor(container, path) {
3357
+ constructor(container, exists, path) {
3263
3358
  this.container = container;
3359
+ this.exists = exists;
3264
3360
  this.path = path;
3265
3361
  this.map = new Map();
3266
3362
  }
@@ -3268,7 +3364,7 @@ class Tree {
3268
3364
  return this.container.parent.tree;
3269
3365
  }
3270
3366
  resolveService() {
3271
- return this.container.resolve(this.path);
3367
+ return !this.exists ? null : this.container.resolve(this.path);
3272
3368
  }
3273
3369
  resolveLeaves() {
3274
3370
  let map;
@@ -3309,7 +3405,7 @@ class Tree {
3309
3405
  parentTree = parentTree.resolveAncestor(path);
3310
3406
  }
3311
3407
  catch (e) {
3312
- parentTree = new Tree(this.container, "");
3408
+ parentTree = new Tree(this.container, false, "");
3313
3409
  }
3314
3410
  const pathParts = path.split(".");
3315
3411
  let tree = this;
@@ -3332,7 +3428,7 @@ class Tree {
3332
3428
  }
3333
3429
  resolvePath(path, throwError = true) {
3334
3430
  const absolutePath = !this.path ? path : `${this.path}.${path}`;
3335
- let tree = new Tree(this.container, absolutePath);
3431
+ let tree = new Tree(this.container, false, absolutePath);
3336
3432
  try {
3337
3433
  tree = this.resolveAncestor(path);
3338
3434
  }
@@ -3355,13 +3451,16 @@ class Tree {
3355
3451
  return this;
3356
3452
  }
3357
3453
  const pathParts = path.split(".");
3454
+ const maxIx = pathParts.length - 1;
3358
3455
  let tree = this;
3359
3456
  path = this.path;
3360
- for (let part of pathParts) {
3457
+ for (let ix = 0; ix <= maxIx; ix++) {
3458
+ const part = pathParts[ix];
3361
3459
  if (!tree.map.has(part)) {
3362
- tree.map.set(part, new Tree(this.container, !path ? part : `${path}.${part}`));
3460
+ tree.map.set(part, new Tree(this.container, false, !path ? part : `${path}.${part}`));
3363
3461
  }
3364
3462
  tree = tree.map.get(part);
3463
+ tree.exists = tree.exists || ix == maxIx;
3365
3464
  path = tree.path;
3366
3465
  }
3367
3466
  return this;
@@ -3375,14 +3474,14 @@ class DiContainer {
3375
3474
  container["wrapperContainer"] = this;
3376
3475
  this.tokens = [];
3377
3476
  this.tokenSet = new Set();
3378
- this.myTree = new Tree(this, "");
3477
+ this.root = new Tree(this, false, "");
3379
3478
  }
3380
3479
  get registeredTokens() {
3381
3480
  var _a;
3382
3481
  return (((_a = this.parent) === null || _a === void 0 ? void 0 : _a.registeredTokens) || []).concat(this.tokens);
3383
3482
  }
3384
3483
  get tree() {
3385
- return this.myTree;
3484
+ return this.root;
3386
3485
  }
3387
3486
  beforeResolution(token, callback, options) {
3388
3487
  this.container.beforeResolution(token, callback, options);
@@ -3443,7 +3542,7 @@ class DiContainer {
3443
3542
  this.tokenSet.add(token);
3444
3543
  this.tokens.push(token);
3445
3544
  if (isString(token)) {
3446
- this.myTree.addPath(token);
3545
+ this.root.addPath(token);
3447
3546
  }
3448
3547
  return this;
3449
3548
  }
@@ -3501,9 +3600,14 @@ class LazyAssetGenerator {
3501
3600
  process() {
3502
3601
  return __awaiter$1(this, void 0, void 0, function* () {
3503
3602
  const lazyAsset = yield this.lazyAssets.read(this.lazyId);
3504
- const progress = yield this.progresses.get(lazyAsset.progressId);
3603
+ let progress = yield this.progresses.get(lazyAsset.progressId);
3604
+ if (!progress || progress.canceled)
3605
+ return null;
3505
3606
  try {
3506
3607
  const asset = yield this.generate(progress);
3608
+ progress = yield progress.load();
3609
+ if (!progress || progress.canceled)
3610
+ return null;
3507
3611
  yield lazyAsset.writeAsset(asset);
3508
3612
  }
3509
3613
  catch (e) {