@stemy/backend 2.9.7 → 3.0.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.
@@ -23,9 +23,8 @@ import sharp_ from 'sharp';
23
23
  import axios from 'axios';
24
24
  import { GridFSBucket } from 'mongodb';
25
25
  import dotenv from 'dotenv';
26
- import { Queue, Worker, Scheduler } from 'node-resque';
27
26
  import { validate, schedule } from 'node-cron';
28
- import ioredis from 'ioredis';
27
+ import { socket } from 'zeromq';
29
28
  import socket_io_client from 'socket.io-client';
30
29
  import { createServer } from 'http';
31
30
  import express_, { static as static$1 } from 'express';
@@ -36,7 +35,7 @@ import * as Handlebars from 'handlebars';
36
35
  import { compare } from 'bcrypt';
37
36
  import moment from 'moment';
38
37
 
39
- var __awaiter$v = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
38
+ var __awaiter$w = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
40
39
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
41
40
  return new (P || (P = Promise))(function (resolve, reject) {
42
41
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -238,7 +237,7 @@ function hydratePopulated(modelType, json) {
238
237
  return object;
239
238
  }
240
239
  function paginateAggregations(model, aggregations, params, metaProjection = {}) {
241
- return __awaiter$v(this, void 0, void 0, function* () {
240
+ return __awaiter$w(this, void 0, void 0, function* () {
242
241
  const sortField = !isString(params.sort) || !params.sort ? null : (params.sort.startsWith("-") ? params.sort.substr(1) : params.sort);
243
242
  const sortAggregation = !sortField ? [] : [{
244
243
  $sort: { [sortField]: sortField == params.sort ? 1 : -1 }
@@ -337,7 +336,7 @@ function readFile(path) {
337
336
  });
338
337
  }
339
338
  function readAndDeleteFile(path, timeout = 5000) {
340
- return __awaiter$v(this, void 0, void 0, function* () {
339
+ return __awaiter$w(this, void 0, void 0, function* () {
341
340
  const data = yield readFile(path);
342
341
  setTimeout(() => {
343
342
  unlink(path, () => {
@@ -347,7 +346,7 @@ function readAndDeleteFile(path, timeout = 5000) {
347
346
  });
348
347
  }
349
348
  function writeFile(path, data) {
350
- return __awaiter$v(this, void 0, void 0, function* () {
349
+ return __awaiter$w(this, void 0, void 0, function* () {
351
350
  yield mkdirRecursive(dirname(path));
352
351
  return new Promise((res, rej) => {
353
352
  writeFile$1(path, data, err => {
@@ -363,10 +362,14 @@ function writeFile(path, data) {
363
362
  function valueToPromise(value) {
364
363
  return value instanceof Promise ? value : Promise.resolve(value);
365
364
  }
366
- function promiseTimeout(timeout = 1000) {
367
- return new Promise((resolve) => {
365
+ function promiseTimeout(timeout = 1000, error = false) {
366
+ return new Promise((resolve, reject) => {
368
367
  setTimeout(() => {
369
- resolve();
368
+ if (error) {
369
+ reject(`Timeout exceeded: ${timeout}ms`);
370
+ return;
371
+ }
372
+ resolve(`Timeout: ${timeout}ms`);
370
373
  }, timeout);
371
374
  });
372
375
  }
@@ -426,7 +429,7 @@ function ResolveEntity(model, extraCheck) {
426
429
  const paramName = modelName.toLowerCase();
427
430
  return createParamDecorator({
428
431
  required: false,
429
- value: (action) => __awaiter$v(this, void 0, void 0, function* () {
432
+ value: (action) => __awaiter$w(this, void 0, void 0, function* () {
430
433
  const req = action.request;
431
434
  const token = req.header(`x-${paramName}-token`);
432
435
  const id = req.params[`${paramName}Id`];
@@ -640,6 +643,68 @@ function runCommand(scriptPath, expectedCode = 0) {
640
643
  console.error(data.toString());
641
644
  });
642
645
  });
646
+ }
647
+ var ConsoleColor;
648
+ (function (ConsoleColor) {
649
+ ConsoleColor["Reset"] = "\u001B[0m";
650
+ ConsoleColor["Bright"] = "\u001B[1m";
651
+ ConsoleColor["Dim"] = "\u001B[2m";
652
+ ConsoleColor["Underscore"] = "\u001B[4m";
653
+ ConsoleColor["Blink"] = "\u001B[5m";
654
+ ConsoleColor["Reverse"] = "\u001B[7m";
655
+ ConsoleColor["Hidden"] = "\u001B[8m";
656
+ ConsoleColor["FgBlack"] = "\u001B[30m";
657
+ ConsoleColor["FgRed"] = "\u001B[31m";
658
+ ConsoleColor["FgGreen"] = "\u001B[32m";
659
+ ConsoleColor["FgYellow"] = "\u001B[33m";
660
+ ConsoleColor["FgBlue"] = "\u001B[34m";
661
+ ConsoleColor["FgMagenta"] = "\u001B[35m";
662
+ ConsoleColor["FgCyan"] = "\u001B[36m";
663
+ ConsoleColor["FgWhite"] = "\u001B[37m";
664
+ ConsoleColor["FgDefault"] = "\u001B[38m";
665
+ ConsoleColor["BgBlack"] = "\u001B[40m";
666
+ ConsoleColor["BgRed"] = "\u001B[41m";
667
+ ConsoleColor["BgGreen"] = "\u001B[42m";
668
+ ConsoleColor["BgYellow"] = "\u001B[43m";
669
+ ConsoleColor["BgBlue"] = "\u001B[44m";
670
+ ConsoleColor["BgMagenta"] = "\u001B[45m";
671
+ ConsoleColor["BgCyan"] = "\u001B[46m";
672
+ ConsoleColor["BgWhite"] = "\u001B[47m";
673
+ ConsoleColor["BgDefault"] = "\u001B[48m";
674
+ })(ConsoleColor || (ConsoleColor = {}));
675
+ const defaultColors = {
676
+ keyColor: ConsoleColor.FgWhite,
677
+ numberColor: ConsoleColor.FgBlue,
678
+ stringColor: ConsoleColor.FgYellow,
679
+ trueColor: ConsoleColor.FgGreen,
680
+ falseColor: ConsoleColor.FgRed,
681
+ nullColor: ConsoleColor.BgMagenta
682
+ };
683
+ function jsonHighlight(input, colorOptions) {
684
+ const colors = Object.assign({}, defaultColors, colorOptions);
685
+ const json = (isString(input) ? input : JSON.stringify(input, null, 2)).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
686
+ return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+]?\d+)?)/g, (match) => {
687
+ let color = colors.numberColor;
688
+ if (/^"/.test(match)) {
689
+ if (/:$/.test(match)) {
690
+ color = colors.keyColor;
691
+ }
692
+ else {
693
+ color = colors.stringColor;
694
+ match = '"' + match.substr(1, match.length - 2) + '"';
695
+ }
696
+ }
697
+ else {
698
+ color = /true/.test(match)
699
+ ? colors.trueColor
700
+ : /false/.test(match)
701
+ ? colors.falseColor
702
+ : /null/.test(match)
703
+ ? colors.nullColor
704
+ : color;
705
+ }
706
+ return `${color}${match}${ConsoleColor.Reset}`;
707
+ });
643
708
  }
644
709
 
645
710
  var __decorate$x = (this && this.__decorate) || function (decorators, target, key, desc) {
@@ -750,7 +815,7 @@ var __decorate$w = (this && this.__decorate) || function (decorators, target, ke
750
815
  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
816
  return c > 3 && r && Object.defineProperty(target, key, r), r;
752
817
  };
753
- var __awaiter$u = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
818
+ var __awaiter$v = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
754
819
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
755
820
  return new (P || (P = Promise))(function (resolve, reject) {
756
821
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -786,7 +851,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
786
851
  }
787
852
  static fileTypeFromBuffer(buffer) {
788
853
  var _a;
789
- return __awaiter$u(this, void 0, void 0, function* () {
854
+ return __awaiter$v(this, void 0, void 0, function* () {
790
855
  const type = ((_a = yield fromBuffer(buffer)) !== null && _a !== void 0 ? _a : { ext: "txt", mime: "text/plain" });
791
856
  if (AssetProcessor_1.checkTextFileType(type)) {
792
857
  return AssetProcessor_1.fixTextFileType(type, buffer);
@@ -813,7 +878,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
813
878
  return imageTypes.indexOf(contentType) >= 0;
814
879
  }
815
880
  static copyImageMeta(buffer, metadata, fileType) {
816
- return __awaiter$u(this, void 0, void 0, function* () {
881
+ return __awaiter$v(this, void 0, void 0, function* () {
817
882
  if (fileType.mime === "image/svg+xml") {
818
883
  const match = /<svg([^<>]+)>/gi.exec(buffer.toString("utf8"));
819
884
  if (match && match.length > 1) {
@@ -852,7 +917,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
852
917
  });
853
918
  }
854
919
  process(buffer, metadata, fileType) {
855
- return __awaiter$u(this, void 0, void 0, function* () {
920
+ return __awaiter$v(this, void 0, void 0, function* () {
856
921
  if (AssetProcessor_1.isImage(fileType.mime)) {
857
922
  buffer = yield AssetProcessor_1.copyImageMeta(buffer, metadata, fileType);
858
923
  }
@@ -929,7 +994,7 @@ var __decorate$u = (this && this.__decorate) || function (decorators, target, ke
929
994
  var __metadata$o = (this && this.__metadata) || function (k, v) {
930
995
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
931
996
  };
932
- var __awaiter$t = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
997
+ var __awaiter$u = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
933
998
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
934
999
  return new (P || (P = Promise))(function (resolve, reject) {
935
1000
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -955,7 +1020,7 @@ let MongoConnector = class MongoConnector {
955
1020
  return this.fsBucket;
956
1021
  }
957
1022
  connect() {
958
- return __awaiter$t(this, void 0, void 0, function* () {
1023
+ return __awaiter$u(this, void 0, void 0, function* () {
959
1024
  if (this.db)
960
1025
  return this.db;
961
1026
  this.conn = (yield connect(this.configuration.resolve("mongoUri"), {
@@ -976,7 +1041,7 @@ MongoConnector = __decorate$u([
976
1041
  __metadata$o("design:paramtypes", [Configuration])
977
1042
  ], MongoConnector);
978
1043
 
979
- var __awaiter$s = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1044
+ var __awaiter$t = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
980
1045
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
981
1046
  return new (P || (P = Promise))(function (resolve, reject) {
982
1047
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -998,7 +1063,7 @@ class BaseEntity {
998
1063
  return this.collection.updateOne({ _id: this.mId }, { $set: this.toJSON() });
999
1064
  }
1000
1065
  load() {
1001
- return __awaiter$s(this, void 0, void 0, function* () {
1066
+ return __awaiter$t(this, void 0, void 0, function* () {
1002
1067
  const res = yield this.collection.findOne({ _id: this.mId });
1003
1068
  this.deleted = !res;
1004
1069
  this.data = res || {};
@@ -1013,7 +1078,7 @@ class BaseEntity {
1013
1078
  }
1014
1079
  }
1015
1080
 
1016
- var __awaiter$r = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1081
+ var __awaiter$s = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1017
1082
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1018
1083
  return new (P || (P = Promise))(function (resolve, reject) {
1019
1084
  function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@@ -1054,13 +1119,14 @@ class Asset extends BaseEntity {
1054
1119
  };
1055
1120
  }
1056
1121
  static toImage(stream, meta, params) {
1057
- return __awaiter$r(this, void 0, void 0, function* () {
1122
+ return __awaiter$s(this, void 0, void 0, function* () {
1058
1123
  params = params || {};
1059
1124
  // Get default crop info
1060
1125
  const crop = Asset.toCropRegion(meta.crop);
1061
- // Return back the stream if there is no params and no default crop exists
1062
- if (Object.keys(params).length == 0 && !crop)
1126
+ // Return the stream if there is no params and no default crop exists
1127
+ if ((meta === null || meta === void 0 ? void 0 : meta.extension) === "svg" || (Object.keys(params).length == 0 && !crop)) {
1063
1128
  return stream;
1129
+ }
1064
1130
  // Parse params
1065
1131
  params.rotation = isNaN(params.rotation) ? 0 : Math.round(params.rotation / 90) * 90;
1066
1132
  params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : Number(params.canvasScaleX);
@@ -1075,51 +1141,43 @@ class Asset extends BaseEntity {
1075
1141
  const cropBefore = Asset.toCropRegion(params.cropBefore || (params.crop ? meta.cropBefore : null));
1076
1142
  const cropAfter = Asset.toCropRegion(params.cropAfter || (params.crop ? meta.cropAfter : null));
1077
1143
  // Get metadata
1078
- const imgMeta = yield sharp$2(buffer).metadata();
1079
- let width = imgMeta.width;
1080
- let height = imgMeta.height;
1144
+ let img = sharp$2(buffer);
1145
+ let { width, height } = yield img.metadata();
1081
1146
  // Crop before resize
1082
1147
  if (cropBefore) {
1083
- buffer = yield sharp$2(buffer)
1084
- .extract(cropBefore)
1085
- .toBuffer();
1086
1148
  width = cropBefore.width;
1087
1149
  height = cropBefore.height;
1150
+ img = img.extract(cropBefore);
1088
1151
  }
1089
1152
  else if (crop) {
1090
- buffer = yield sharp$2(buffer)
1091
- .extract(crop)
1092
- .toBuffer();
1093
1153
  width = crop.width;
1094
1154
  height = crop.height;
1155
+ img = img.extract(crop);
1095
1156
  }
1096
1157
  // Resize canvas
1097
- if (params.canvasScaleX !== 1 || params.canvasScaleY !== 1) {
1158
+ const canvasScaleX = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleX) || 1;
1159
+ const canvasScaleY = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleY) || 1;
1160
+ if (params.canvasScaleX !== canvasScaleX || params.canvasScaleY !== canvasScaleY) {
1098
1161
  width = Math.round(width * params.canvasScaleX);
1099
1162
  height = Math.round(height * params.canvasScaleY);
1100
- buffer = yield sharp$2(buffer)
1101
- .resize({ width, height, background: "#00000000", fit: "contain" })
1102
- .toBuffer();
1163
+ img = img.resize({ width, height, background: "#00000000", fit: "contain" });
1103
1164
  }
1104
1165
  // Resize image
1105
1166
  if (params.scaleX !== 1 || params.scaleY !== 1) {
1106
1167
  width = Math.round(width * params.scaleX);
1107
1168
  height = Math.round(height * params.scaleY);
1108
- buffer = yield sharp$2(buffer)
1109
- .resize({ width, height, background: "#00000000", fit: "fill" })
1110
- .toBuffer();
1169
+ img = img.resize({ width, height, background: "#00000000", fit: "fill" });
1111
1170
  }
1112
1171
  // Crop after resize
1113
1172
  if (cropAfter) {
1114
- buffer = yield sharp$2(buffer)
1115
- .extract(cropAfter)
1116
- .toBuffer();
1173
+ img = img.extract(cropAfter);
1117
1174
  }
1118
1175
  // Rotate
1119
1176
  if (params.rotation !== 0) {
1120
- buffer = yield sharp$2(buffer).rotate(params.rotation).toBuffer();
1177
+ buffer = yield img.toBuffer();
1178
+ img = sharp$2(buffer).rotate(params.rotation);
1121
1179
  }
1122
- return bufferToStream(buffer);
1180
+ return bufferToStream(yield img.toBuffer());
1123
1181
  }
1124
1182
  catch (e) {
1125
1183
  console.log("Asset image conversion error", e);
@@ -1140,7 +1198,7 @@ class Asset extends BaseEntity {
1140
1198
  return this.bucket.openDownloadStream(this.mId);
1141
1199
  }
1142
1200
  unlink() {
1143
- return __awaiter$r(this, void 0, void 0, function* () {
1201
+ return __awaiter$s(this, void 0, void 0, function* () {
1144
1202
  return deleteFromBucket(this.bucket, this.mId);
1145
1203
  });
1146
1204
  }
@@ -1148,7 +1206,7 @@ class Asset extends BaseEntity {
1148
1206
  return streamToBuffer(this.stream);
1149
1207
  }
1150
1208
  download(metadata) {
1151
- return __awaiter$r(this, void 0, void 0, function* () {
1209
+ return __awaiter$s(this, void 0, void 0, function* () {
1152
1210
  metadata = Object.assign(this.metadata, metadata || {});
1153
1211
  metadata.downloadCount = isNaN(metadata.downloadCount) || !metadata.firstDownload
1154
1212
  ? 1
@@ -1160,17 +1218,79 @@ class Asset extends BaseEntity {
1160
1218
  });
1161
1219
  }
1162
1220
  getImage(params = null) {
1163
- return __awaiter$r(this, void 0, void 0, function* () {
1221
+ return __awaiter$s(this, void 0, void 0, function* () {
1164
1222
  return Asset.toImage(this.stream, this.metadata, params);
1165
1223
  });
1166
1224
  }
1167
1225
  downloadImage(params, metadata) {
1168
- return __awaiter$r(this, void 0, void 0, function* () {
1226
+ return __awaiter$s(this, void 0, void 0, function* () {
1169
1227
  return Asset.toImage(yield this.download(metadata), this.metadata, params);
1170
1228
  });
1171
1229
  }
1172
1230
  }
1173
1231
 
1232
+ var __awaiter$r = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1233
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1234
+ return new (P || (P = Promise))(function (resolve, reject) {
1235
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1236
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1237
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1238
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1239
+ });
1240
+ };
1241
+ class TempAsset {
1242
+ constructor(buffer, filename, contentType, metadata) {
1243
+ this.buffer = buffer;
1244
+ this.filename = filename;
1245
+ this.contentType = contentType;
1246
+ this.metadata = metadata;
1247
+ this.id = new ObjectId().toHexString();
1248
+ }
1249
+ get stream() {
1250
+ return bufferToStream(this.buffer);
1251
+ }
1252
+ unlink() {
1253
+ return __awaiter$r(this, void 0, void 0, function* () {
1254
+ throw new Error(`Temp asset '${this.id}' can not be removed!`);
1255
+ });
1256
+ }
1257
+ getBuffer() {
1258
+ return __awaiter$r(this, void 0, void 0, function* () {
1259
+ return this.buffer;
1260
+ });
1261
+ }
1262
+ download(metadata) {
1263
+ return __awaiter$r(this, void 0, void 0, function* () {
1264
+ return this.stream;
1265
+ });
1266
+ }
1267
+ downloadImage(params, metadata) {
1268
+ Object.assign(this.metadata, metadata || {});
1269
+ return Asset.toImage(this.stream, this.metadata, params);
1270
+ }
1271
+ getImage(params) {
1272
+ return this.downloadImage(params);
1273
+ }
1274
+ save() {
1275
+ return __awaiter$r(this, void 0, void 0, function* () {
1276
+ return this;
1277
+ });
1278
+ }
1279
+ load() {
1280
+ return __awaiter$r(this, void 0, void 0, function* () {
1281
+ return this;
1282
+ });
1283
+ }
1284
+ toJSON() {
1285
+ return {
1286
+ id: this.id,
1287
+ filename: this.filename,
1288
+ contentType: this.contentType,
1289
+ metadata: this.metadata
1290
+ };
1291
+ }
1292
+ }
1293
+
1174
1294
  var __decorate$t = (this && this.__decorate) || function (decorators, target, key, desc) {
1175
1295
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1176
1296
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1238,6 +1358,27 @@ let Assets = class Assets {
1238
1358
  return this.writeBuffer(buffer, metadata);
1239
1359
  });
1240
1360
  }
1361
+ download(url, contentType = null) {
1362
+ return __awaiter$q(this, void 0, void 0, function* () {
1363
+ let buffer = (yield axios({ url, responseType: "arraybuffer" })).data;
1364
+ let fileType = { ext: "", mime: contentType };
1365
+ try {
1366
+ fileType = yield AssetProcessor.fileTypeFromBuffer(buffer);
1367
+ }
1368
+ catch (e) {
1369
+ if (!fileType.mime) {
1370
+ throw `Can't determine mime type`;
1371
+ }
1372
+ console.log(`Can't determine mime type`, e);
1373
+ }
1374
+ const metadata = {
1375
+ filename: url,
1376
+ extension: (fileType.ext || "").trim()
1377
+ };
1378
+ buffer = yield this.assetProcessor.process(buffer, metadata, fileType);
1379
+ return new TempAsset(buffer, url, fileType.mime, metadata);
1380
+ });
1381
+ }
1241
1382
  read(id) {
1242
1383
  return __awaiter$q(this, void 0, void 0, function* () {
1243
1384
  return !id ? null : this.find({ _id: new ObjectId(id) });
@@ -1355,7 +1496,7 @@ class LazyAsset extends BaseEntity {
1355
1496
  this.progresses.get(this.progressId).then(p => {
1356
1497
  p === null || p === void 0 ? void 0 : p.cancel();
1357
1498
  });
1358
- this.startWorkingOnAsset().then(() => {
1499
+ this.startWorkingOnAsset(false).then(() => {
1359
1500
  console.log(`Started working on lazy asset: ${this.id}`);
1360
1501
  }).catch(reason => {
1361
1502
  console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
@@ -1374,7 +1515,7 @@ class LazyAsset extends BaseEntity {
1374
1515
  yield this.progresses.waitToFinish(this.progressId);
1375
1516
  return this.loadAsset();
1376
1517
  }
1377
- yield this.startWorkingOnAsset();
1518
+ yield this.startWorkingOnAsset(true);
1378
1519
  return this.loadAsset();
1379
1520
  });
1380
1521
  }
@@ -1385,12 +1526,12 @@ class LazyAsset extends BaseEntity {
1385
1526
  return asset;
1386
1527
  });
1387
1528
  }
1388
- startWorkingOnAsset() {
1529
+ startWorkingOnAsset(fromLoad) {
1389
1530
  return __awaiter$p(this, void 0, void 0, function* () {
1390
1531
  this.data.progressId = (yield this.progresses.create()).id;
1391
1532
  this.data.assetId = null;
1392
1533
  yield this.save();
1393
- yield this.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id }));
1534
+ yield this.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id, fromLoad }));
1394
1535
  });
1395
1536
  }
1396
1537
  }
@@ -1416,15 +1557,15 @@ var __awaiter$o = (this && this.__awaiter) || function (thisArg, _arguments, P,
1416
1557
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1417
1558
  });
1418
1559
  };
1419
- const IORedis = ioredis;
1420
1560
  let JobManager = class JobManager {
1421
1561
  constructor(config, container, jobTypes) {
1422
1562
  this.config = config;
1423
1563
  this.container = container;
1424
1564
  this.jobTypes = jobTypes || [];
1425
1565
  this.jobs = this.jobTypes.reduce((res, jobType) => {
1426
- res[getConstructorName(jobType)] = {
1427
- perform: this.toPerformFunction(jobType)
1566
+ res[getConstructorName(jobType)] = (jobParams) => {
1567
+ const job = this.resolveJobInstance(jobType, jobParams);
1568
+ return job.process();
1428
1569
  };
1429
1570
  return res;
1430
1571
  }, {});
@@ -1442,31 +1583,25 @@ let JobManager = class JobManager {
1442
1583
  return instance.process();
1443
1584
  });
1444
1585
  }
1445
- enqueueWithName(name, params = {}, que = "main") {
1586
+ enqueueWithName(name, params = {}) {
1446
1587
  return __awaiter$o(this, void 0, void 0, function* () {
1447
1588
  const jobName = yield this.tryResolveFromName(name, params);
1448
- yield this.queue.enqueue(que, jobName, [params]);
1449
- });
1450
- }
1451
- enqueue(jobType, params = {}, que = "main") {
1452
- return __awaiter$o(this, void 0, void 0, function* () {
1453
- const jobName = yield this.tryResolveAndConnect(jobType, params);
1454
- yield this.queue.enqueue(que, jobName, [params]);
1589
+ return this.sendToWorkers(jobName, params);
1455
1590
  });
1456
1591
  }
1457
- enqueueAt(timestamp, jobType, params = {}, que = "main") {
1592
+ enqueue(jobType, params = {}) {
1458
1593
  return __awaiter$o(this, void 0, void 0, function* () {
1459
1594
  const jobName = yield this.tryResolveAndConnect(jobType, params);
1460
- yield this.queue.enqueueAt(timestamp, que, jobName, [params]);
1595
+ return this.sendToWorkers(jobName, params);
1461
1596
  });
1462
1597
  }
1463
- enqueueIn(time, jobType, params = {}, que = "main") {
1598
+ sendToWorkers(jobName, params) {
1464
1599
  return __awaiter$o(this, void 0, void 0, function* () {
1465
- const jobName = yield this.tryResolveAndConnect(jobType, params);
1466
- yield this.queue.enqueueIn(time, que, jobName, [params]);
1600
+ const publisher = yield this.scheduler;
1601
+ yield publisher.send([jobName, JSON.stringify(params), new ObjectId().toHexString()]);
1467
1602
  });
1468
1603
  }
1469
- schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}, que = "main") {
1604
+ schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}) {
1470
1605
  const expression = [minute, hour, dayOfMonth, month, dayOfWeek].map(t => {
1471
1606
  if (isObject(t)) {
1472
1607
  const range = t;
@@ -1483,19 +1618,38 @@ let JobManager = class JobManager {
1483
1618
  return null;
1484
1619
  }
1485
1620
  return schedule(expression, () => {
1486
- this.enqueue(jobType, params, que).catch(e => {
1621
+ this.enqueue(jobType, params).catch(e => {
1487
1622
  console.log(`Can't enqueue job: '${jobName}' because: ${e}`);
1488
1623
  });
1489
1624
  });
1490
1625
  }
1491
1626
  startProcessing() {
1492
- return __awaiter$o(this, void 0, void 0, function* () {
1493
- this.initialize();
1494
- yield this.worker.connect();
1495
- yield this.worker.start();
1496
- yield this.scheduler.connect();
1497
- yield this.scheduler.start();
1498
- });
1627
+ const host = this.config.resolve("zmqRemoteHost");
1628
+ this.worker = socket("pull");
1629
+ this.worker.connect(host);
1630
+ this.worker.on("message", (name, args, uniqueId) => __awaiter$o(this, void 0, void 0, function* () {
1631
+ try {
1632
+ const jobName = name.toString("utf8");
1633
+ const jobParams = JSON.parse(args.toString("utf8"));
1634
+ const timerId = uniqueId === null || uniqueId === void 0 ? void 0 : uniqueId.toString("utf8");
1635
+ const jobNameLog = `\x1b[36m"${jobName}"\x1b[0m`;
1636
+ const jobArgsLog = `\n${jsonHighlight(jobParams)}`;
1637
+ console.time(timerId);
1638
+ console.timeLog(timerId, `Started working on background job: ${jobNameLog} with args: ${jobArgsLog}\n\n`);
1639
+ try {
1640
+ yield Promise.race([this.jobs[jobName](jobParams), promiseTimeout(15000, true)]);
1641
+ console.timeLog(timerId, `Finished working on background job: ${jobNameLog}\n\n`);
1642
+ }
1643
+ catch (e) {
1644
+ console.timeLog(timerId, `Background job failed: ${jobNameLog}\n${e.message}\n\n`);
1645
+ }
1646
+ console.timeEnd(timerId);
1647
+ }
1648
+ catch (e) {
1649
+ console.log(`Failed to start job: ${e.message}`);
1650
+ }
1651
+ }));
1652
+ console.log(`Waiting for jobs at: ${host}`);
1499
1653
  }
1500
1654
  tryResolve(jobType, params) {
1501
1655
  const jobName = getConstructorName(jobType);
@@ -1510,47 +1664,6 @@ let JobManager = class JobManager {
1510
1664
  }
1511
1665
  return jobName;
1512
1666
  }
1513
- initialize() {
1514
- if (this.queue)
1515
- return;
1516
- const config = this.config;
1517
- const options = { password: config.resolve("redisPassword") };
1518
- const sentinels = config.resolve("redisSentinels");
1519
- const redis = !sentinels
1520
- ? null
1521
- : new IORedis({
1522
- sentinels,
1523
- name: config.resolve("redisCluster"),
1524
- });
1525
- const connection = {
1526
- pkg: "ioredis",
1527
- host: config.resolve("redisHost"),
1528
- password: options.password,
1529
- port: config.resolve("redisPort"),
1530
- namespace: config.resolve("redisNamespace"),
1531
- redis,
1532
- options
1533
- };
1534
- const queues = config.resolve("workQueues");
1535
- this.queue = new Queue({ connection }, this.jobs);
1536
- this.worker = new Worker({ connection, queues }, this.jobs);
1537
- this.worker.on("job", (queue, job) => {
1538
- console.log(`working job ${queue} ${JSON.stringify(job)}`);
1539
- });
1540
- this.worker.on("reEnqueue", (queue, job, plugin) => {
1541
- console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
1542
- });
1543
- this.worker.on("success", (queue, job, result, duration) => {
1544
- console.log(`job success ${queue} ${JSON.stringify(job)} >> ${result} (${duration}ms)`);
1545
- });
1546
- this.worker.on("failure", (queue, job, failure, duration) => {
1547
- console.log(`job failure ${queue} ${JSON.stringify(job)} >> ${failure} (${duration}ms)`);
1548
- });
1549
- this.worker.on("error", (error, queue, job) => {
1550
- console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`);
1551
- });
1552
- this.scheduler = new Scheduler({ connection }, this.jobs);
1553
- }
1554
1667
  tryResolveFromName(jobName, params) {
1555
1668
  const jobType = this.jobTypes.find(type => {
1556
1669
  return getConstructorName(type) == jobName;
@@ -1562,10 +1675,14 @@ let JobManager = class JobManager {
1562
1675
  }
1563
1676
  tryResolveAndConnect(jobType, params) {
1564
1677
  return __awaiter$o(this, void 0, void 0, function* () {
1565
- this.initialize();
1566
- const jobName = this.tryResolve(jobType, params);
1567
- yield this.queue.connect();
1568
- return jobName;
1678
+ this.scheduler = this.scheduler || new Promise((resolve) => __awaiter$o(this, void 0, void 0, function* () {
1679
+ const port = this.config.resolve("zmqPort");
1680
+ const publisher = socket("push");
1681
+ yield publisher.bind(`tcp://0.0.0.0:${port}`);
1682
+ console.log(`Publisher bound to port: ${port}`);
1683
+ resolve(publisher);
1684
+ }));
1685
+ return this.tryResolve(jobType, params);
1569
1686
  });
1570
1687
  }
1571
1688
  resolveJobInstance(jobType, params) {
@@ -1576,12 +1693,6 @@ let JobManager = class JobManager {
1576
1693
  container.register(jobType, jobType);
1577
1694
  return container.resolve(jobType);
1578
1695
  }
1579
- toPerformFunction(jobType) {
1580
- return (jobParams) => {
1581
- const job = this.resolveJobInstance(jobType, jobParams);
1582
- return job.process();
1583
- };
1584
- }
1585
1696
  };
1586
1697
  JobManager = __decorate$s([
1587
1698
  injectable(),
@@ -2903,7 +3014,9 @@ let AssetsController = class AssetsController {
2903
3014
  getImageRotation(id, params, res, rotation = 0) {
2904
3015
  return __awaiter$7(this, void 0, void 0, function* () {
2905
3016
  const asset = yield this.getAsset("Image", id, params.lazy, res);
2906
- params.rotation = params.rotation || rotation;
3017
+ if (rotation !== 0) {
3018
+ params.rotation = params.rotation || rotation;
3019
+ }
2907
3020
  return asset.downloadImage(params);
2908
3021
  });
2909
3022
  }
@@ -3714,20 +3827,8 @@ function createServices() {
3714
3827
  new Parameter("mongoPassword", null),
3715
3828
  new Parameter("nodeEnv", "development"),
3716
3829
  new Parameter("appPort", 80),
3717
- new Parameter("redisHost", "127.0.0.1"),
3718
- new Parameter("redisPort", 6379),
3719
- new Parameter("redisPassword", "123456"),
3720
- new Parameter("redisNamespace", "resque"),
3721
- new Parameter("redisCluster", "mymaster"),
3722
- new Parameter("redisSentinels", null, value => {
3723
- if (!value)
3724
- return null;
3725
- return value.split(", ").map(item => {
3726
- const values = item.split(":");
3727
- return { host: values[0], port: Number(values[1]) };
3728
- });
3729
- }),
3730
- new Parameter("workQueues", ["main"]),
3830
+ new Parameter("zmqPort", 3000),
3831
+ new Parameter("zmqRemoteHost", "tcp://127.0.0.1:3000"),
3731
3832
  new Parameter("isWorker", false),
3732
3833
  new Parameter("mainEndpoint", ""),
3733
3834
  new Parameter("idChars", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
@@ -3933,5 +4034,5 @@ function setupBackend(config, providers, parent) {
3933
4034
  * Generated bundle index. Do not edit.
3934
4035
  */
3935
4036
 
3936
- export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isPrimitive, isString, isType, lastItem, lcFirst, lookupPipelines, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, runCommand, setupBackend, streamToBuffer, ucFirst, valueToPromise, writeFile };
4037
+ export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, ConsoleColor, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isPrimitive, isString, isType, jsonHighlight, lastItem, lcFirst, lookupPipelines, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, runCommand, setupBackend, streamToBuffer, ucFirst, valueToPromise, writeFile };
3937
4038
  //# sourceMappingURL=stemy-backend.js.map