@stemy/backend 4.0.0 → 4.0.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.
Files changed (41) hide show
  1. package/esm2020/commands/fixtures-command.mjs +5 -3
  2. package/esm2020/requests/asset-image-params.mjs +20 -11
  3. package/esm2020/rest-controllers/assets.controller.mjs +35 -10
  4. package/esm2020/rest-controllers/auth.controller.mjs +14 -5
  5. package/esm2020/rest-controllers/gallery.controller.mjs +9 -4
  6. package/esm2020/rest-controllers/progresses.controller.mjs +10 -4
  7. package/esm2020/rest-controllers/terminal.controller.mjs +17 -6
  8. package/esm2020/rest-middlewares/container.middleware.mjs +4 -3
  9. package/esm2020/rest-middlewares/error-handler.middleware.mjs +6 -3
  10. package/esm2020/rest-middlewares/language.middleware.mjs +5 -3
  11. package/esm2020/rest-middlewares/request-ended.middleware.mjs +5 -3
  12. package/esm2020/rest-middlewares/request-started.middleware.mjs +5 -3
  13. package/esm2020/services/asset-resolver.mjs +6 -3
  14. package/esm2020/services/assets.mjs +6 -3
  15. package/esm2020/services/backend-provider.mjs +4 -3
  16. package/esm2020/services/cache.mjs +7 -3
  17. package/esm2020/services/configuration.mjs +4 -3
  18. package/esm2020/services/fixtures.mjs +4 -3
  19. package/esm2020/services/gallery-cache.mjs +4 -3
  20. package/esm2020/services/gallery.mjs +6 -3
  21. package/esm2020/services/id-generator.mjs +5 -3
  22. package/esm2020/services/job-manager.mjs +7 -3
  23. package/esm2020/services/lazy-assets.mjs +13 -3
  24. package/esm2020/services/logger.mjs +5 -3
  25. package/esm2020/services/mail-sender.mjs +6 -3
  26. package/esm2020/services/memory-cache.mjs +5 -3
  27. package/esm2020/services/mongo-connector.mjs +5 -3
  28. package/esm2020/services/open-api.mjs +4 -3
  29. package/esm2020/services/progresses.mjs +6 -3
  30. package/esm2020/services/template-renderer.mjs +6 -3
  31. package/esm2020/services/terminal-manager.mjs +7 -3
  32. package/esm2020/services/token-generator.mjs +4 -3
  33. package/esm2020/services/translation-provider.mjs +6 -3
  34. package/esm2020/services/translator.mjs +5 -3
  35. package/esm2020/socket-controllers/progress.controller.mjs +14 -5
  36. package/esm2020/socket-controllers/terminal.controller.mjs +17 -6
  37. package/fesm2015/stemy-backend.mjs +1303 -1196
  38. package/fesm2015/stemy-backend.mjs.map +1 -1
  39. package/fesm2020/stemy-backend.mjs +1369 -1262
  40. package/fesm2020/stemy-backend.mjs.map +1 -1
  41. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { __awaiter, __decorate, __param } from 'tslib';
1
+ import { __awaiter, __decorate, __param, __metadata } from 'tslib';
2
2
  import { dirname, basename, join, resolve } from 'path';
3
3
  import bodyParser from 'body-parser';
4
4
  import webToken from 'jsonwebtoken';
@@ -19,19 +19,19 @@ import { ObjectId, GridFSBucket } from 'mongodb';
19
19
  import { Types, connect, model } from 'mongoose';
20
20
  import { Readable, PassThrough } from 'stream';
21
21
  import { fileTypeFromStream } from 'file-type/core';
22
- import { createServer } from 'http';
23
- import express_, { static as static$1 } from 'express';
24
- import { Server } from 'socket.io';
25
22
  import dotenv from 'dotenv';
26
- import { v4 } from 'uuid';
27
23
  import cron from 'node-cron';
28
24
  import { socket } from 'zeromq';
29
25
  import { filter as filter$1, map, first, timeout } from 'rxjs/operators';
26
+ import { createServer } from 'http';
27
+ import express_, { static as static$1 } from 'express';
28
+ import { Server } from 'socket.io';
29
+ import { v4 } from 'uuid';
30
30
  import { createTransport } from 'nodemailer';
31
+ import * as Handlebars from 'handlebars';
31
32
  import { routingControllersToSpec, OpenAPI, getStatusCode } from 'routing-controllers-openapi';
32
33
  import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
33
34
  import { ValidatorConstraint, ValidationTypes, Min, Max, IsOptional, IsBoolean } from 'class-validator';
34
- import * as Handlebars from 'handlebars';
35
35
  import { CommandsAddon, AnsiCodes } from '@stemy/terminal-commands-addon';
36
36
  import { compare } from 'bcrypt';
37
37
  import moment from 'moment';
@@ -148,36 +148,6 @@ AssetProcessor = AssetProcessor_1 = __decorate([
148
148
  scoped(Lifecycle.ContainerScoped)
149
149
  ], AssetProcessor);
150
150
 
151
- let AssetResolver = class AssetResolver {
152
- constructor(assets, lazyAssets) {
153
- this.assets = assets;
154
- this.lazyAssets = lazyAssets;
155
- }
156
- resolve(id, lazy = false) {
157
- return __awaiter(this, void 0, void 0, function* () {
158
- let asset = null;
159
- if (lazy) {
160
- const lazyAsset = yield this.lazyAssets.read(id);
161
- if (!lazyAsset)
162
- return null;
163
- return lazyAsset.loadAsset();
164
- }
165
- asset = yield this.assets.read(id);
166
- if (!asset) {
167
- const lazyAsset = yield this.lazyAssets.read(id);
168
- if (!lazyAsset)
169
- return null;
170
- return lazyAsset.loadAsset();
171
- }
172
- return asset;
173
- });
174
- }
175
- };
176
- AssetResolver = __decorate([
177
- injectable(),
178
- scoped(Lifecycle.ContainerScoped)
179
- ], AssetResolver);
180
-
181
151
  const sharp$2 = sharp_;
182
152
  const diContainers = {
183
153
  appContainer: null
@@ -866,6 +836,101 @@ function fileTypeFromBuffer(buffer) {
866
836
  });
867
837
  }
868
838
 
839
+ let Configuration = class Configuration {
840
+ constructor(params) {
841
+ dotenv.config();
842
+ this.paramMap = {};
843
+ this.paramValues = {};
844
+ (params || []).forEach(param => this.add(param));
845
+ }
846
+ add(param) {
847
+ const existingParam = this.paramMap[param.name] || param;
848
+ existingParam.defaultValue = param.defaultValue;
849
+ existingParam.resolver = param.resolver || existingParam.resolver;
850
+ this.paramMap[param.name] = existingParam;
851
+ }
852
+ resolveValue(param, alreadyResolved) {
853
+ const envName = param.name.replace(/\.?([A-Z|0-9]+)/g, function (x, y) {
854
+ return "_" + y.toLowerCase();
855
+ }).replace(/\./gi, "_").replace(/^_/, "").toUpperCase();
856
+ const envValue = process.env[envName];
857
+ const helper = (p) => this.resolveInternal(p, alreadyResolved);
858
+ if (typeof envValue !== "undefined") {
859
+ const value = isFunction(param.resolver)
860
+ ? param.resolver(envValue, helper)
861
+ : convertValue(envValue, getType(param.defaultValue));
862
+ console.log(colorize(`Processing param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), colorize(envName, ConsoleColor.FgBlue), `"${envValue}"`, value);
863
+ return value;
864
+ }
865
+ else if (isFunction(param.resolver)) {
866
+ const value = param.resolver(param.defaultValue, helper);
867
+ console.log(colorize(`Processing default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue, value);
868
+ return value;
869
+ }
870
+ console.log(colorize(`Using default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue);
871
+ return param.defaultValue;
872
+ }
873
+ hasParam(name) {
874
+ return !!this.paramMap[name];
875
+ }
876
+ resolve(name) {
877
+ return this.resolveInternal(name, []);
878
+ }
879
+ resolveInternal(name, alreadyResolved) {
880
+ if (alreadyResolved.includes(name)) {
881
+ throw new Error(`Circular dependency detected: ${alreadyResolved.join(" -> ")} -> ${name}`);
882
+ }
883
+ alreadyResolved.push(name);
884
+ const param = this.paramMap[name];
885
+ if (!param)
886
+ throw new Error(`Parameter with name: '${name}' does not exists in configuration`);
887
+ if (!(name in this.paramValues)) {
888
+ this.paramValues[name] = this.resolveValue(param, alreadyResolved);
889
+ }
890
+ return this.paramValues[name];
891
+ }
892
+ };
893
+ Configuration = __decorate([
894
+ singleton(),
895
+ __param(0, injectAll(PARAMETER)),
896
+ __metadata("design:paramtypes", [Array])
897
+ ], Configuration);
898
+
899
+ let MongoConnector = class MongoConnector {
900
+ constructor(configuration) {
901
+ this.configuration = configuration;
902
+ this.conn = null;
903
+ this.db = null;
904
+ this.fsBucket = null;
905
+ }
906
+ get connection() {
907
+ return this.conn;
908
+ }
909
+ get database() {
910
+ return this.db;
911
+ }
912
+ get bucket() {
913
+ return this.fsBucket;
914
+ }
915
+ connect() {
916
+ return __awaiter(this, void 0, void 0, function* () {
917
+ if (this.db)
918
+ return this.db;
919
+ this.conn = (yield connect(this.configuration.resolve("mongoUri"), {
920
+ dbName: this.configuration.resolve("mongoDb"),
921
+ user: this.configuration.resolve("mongoUser"),
922
+ pass: this.configuration.resolve("mongoPassword")
923
+ })).connection;
924
+ this.db = this.conn.db;
925
+ this.fsBucket = new GridFSBucket(this.db, { bucketName: "assets" });
926
+ });
927
+ }
928
+ };
929
+ MongoConnector = __decorate([
930
+ singleton(),
931
+ __metadata("design:paramtypes", [Configuration])
932
+ ], MongoConnector);
933
+
869
934
  class BaseEntity {
870
935
  constructor(mId, data, collection) {
871
936
  this.mId = mId;
@@ -1146,416 +1211,106 @@ let Assets = class Assets {
1146
1211
  };
1147
1212
  Assets = __decorate([
1148
1213
  injectable(),
1149
- scoped(Lifecycle.ContainerScoped)
1214
+ scoped(Lifecycle.ContainerScoped),
1215
+ __metadata("design:paramtypes", [MongoConnector, AssetProcessor])
1150
1216
  ], Assets);
1151
1217
 
1152
- const express = express_;
1153
- let BackendProvider = class BackendProvider {
1154
- constructor() {
1155
- this.express = express();
1156
- this.express.set("trust proxy", true);
1157
- this.server = createServer(this.express);
1218
+ class LazyAsset extends BaseEntity {
1219
+ constructor(id, data, collection, logger, assets, progresses) {
1220
+ super(id, data, collection);
1221
+ this.logger = logger;
1222
+ this.assets = assets;
1223
+ this.progresses = progresses;
1158
1224
  }
1159
- get io() {
1160
- this.ioServer = this.ioServer || new Server(this.server, { path: "/socket" });
1161
- return this.ioServer;
1225
+ get jobName() {
1226
+ return this.data.jobName;
1162
1227
  }
1163
- };
1164
- BackendProvider = __decorate([
1165
- singleton()
1166
- ], BackendProvider);
1167
-
1168
- let Cache = class Cache {
1169
- constructor(connector, config, cacheProcessor) {
1170
- this.connector = connector;
1171
- this.config = config;
1172
- this.cacheProcessor = cacheProcessor;
1228
+ get jobParams() {
1229
+ return this.data.jobParams;
1173
1230
  }
1174
- prepare() {
1231
+ get jobQue() {
1232
+ return this.data.jobQue;
1233
+ }
1234
+ get progressId() {
1235
+ return this.data.progressId;
1236
+ }
1237
+ get assetId() {
1238
+ return this.data.assetId;
1239
+ }
1240
+ unlink() {
1175
1241
  return __awaiter(this, void 0, void 0, function* () {
1176
- if (this.collection)
1177
- return;
1178
- if (!this.connector.database) {
1179
- throw new Error(`You can't use cache without mongo connection!`);
1242
+ yield this.load();
1243
+ if (!this.progressId) {
1244
+ yield this.collection.deleteOne({ _id: this.mId });
1180
1245
  }
1181
- this.collection = this.connector.database.collection(this.config.resolve("cacheCollection"));
1182
- yield this.collection.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
1246
+ return deleteFromBucket(this.assets.bucket, new ObjectId$1(this.assetId));
1183
1247
  });
1184
1248
  }
1185
- set(key, value, ttl, expirationTimestamp = null, tags = {}) {
1186
- return __awaiter(this, void 0, void 0, function* () {
1187
- yield this.prepare();
1188
- const item = {
1189
- _id: key,
1190
- data: yield this.cacheProcessor.serialize(value),
1191
- tags: yield this.cacheProcessor.serialize(tags),
1192
- expirationTimestamp,
1193
- };
1194
- if (ttl) {
1195
- const now = Math.round(new Date().getTime() / 1000);
1196
- item.expiresAt = now + ttl;
1197
- }
1198
- yield this.collection.updateOne({ _id: key }, { $set: item }, { upsert: true });
1199
- return value;
1249
+ startWorking() {
1250
+ this.load().then(() => {
1251
+ if (this.deleted)
1252
+ return;
1253
+ this.progresses.get(this.progressId).then(p => {
1254
+ p === null || p === void 0 ? void 0 : p.cancel();
1255
+ });
1256
+ this.startWorkingOnAsset(false).then(() => {
1257
+ this.logger.log("lazy-assets", `Started working on lazy asset: ${this.id}`);
1258
+ }).catch(reason => {
1259
+ this.logger.log("lazy-assets", `Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1260
+ });
1200
1261
  });
1201
1262
  }
1202
- get(key) {
1263
+ loadAsset() {
1203
1264
  return __awaiter(this, void 0, void 0, function* () {
1204
- yield this.prepare();
1205
- let item = yield this.collection.findOne({ _id: key });
1206
- const now = Math.round(new Date().getTime() / 1000);
1207
- if (item && item.expiresAt && item.expiresAt < now) {
1208
- item = null;
1265
+ yield this.load();
1266
+ if (this.deleted)
1267
+ return null;
1268
+ if (this.assetId) {
1269
+ return this.assets.read(this.assetId);
1209
1270
  }
1210
- if (!item) {
1211
- throw new Error(`Cache probably doesn't exists with key: ${key}`);
1271
+ if (this.progressId) {
1272
+ yield this.progresses.waitToFinish(this.progressId);
1273
+ return this.loadAsset();
1212
1274
  }
1213
- return yield this.cacheProcessor.deserialize(item.data);
1275
+ yield this.startWorkingOnAsset(true);
1276
+ return this.loadAsset();
1214
1277
  });
1215
1278
  }
1216
- getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
1279
+ writeAsset(asset) {
1217
1280
  return __awaiter(this, void 0, void 0, function* () {
1218
- try {
1219
- return yield this.get(key);
1220
- }
1221
- catch (e) {
1222
- return yield this.set(key, yield valueCb(), ttl, expirationTimestamp, tags);
1223
- }
1281
+ this.data.assetId = asset.id;
1282
+ yield this.save();
1283
+ return asset;
1224
1284
  });
1225
1285
  }
1226
- delete(key) {
1286
+ startWorkingOnAsset(fromLoad) {
1227
1287
  return __awaiter(this, void 0, void 0, function* () {
1228
- yield this.prepare();
1229
- yield this.collection.deleteOne({ _id: key });
1288
+ this.data.progressId = (yield this.progresses.create()).id;
1289
+ this.data.assetId = null;
1290
+ yield this.save();
1291
+ yield this.progresses.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id, fromLoad }));
1230
1292
  });
1231
1293
  }
1232
- };
1233
- Cache = __decorate([
1234
- singleton()
1235
- ], Cache);
1294
+ }
1236
1295
 
1237
- let CacheProcessor = class CacheProcessor {
1238
- serialize(data) {
1239
- return __awaiter(this, void 0, void 0, function* () {
1240
- return data;
1241
- });
1242
- }
1243
- deserialize(data) {
1244
- return __awaiter(this, void 0, void 0, function* () {
1245
- return data;
1246
- });
1247
- }
1248
- };
1249
- CacheProcessor = __decorate([
1250
- injectable(),
1251
- scoped(Lifecycle.ContainerScoped)
1252
- ], CacheProcessor);
1253
-
1254
- let Configuration = class Configuration {
1255
- constructor(params) {
1256
- dotenv.config();
1257
- this.paramMap = {};
1258
- this.paramValues = {};
1259
- (params || []).forEach(param => this.add(param));
1260
- }
1261
- add(param) {
1262
- const existingParam = this.paramMap[param.name] || param;
1263
- existingParam.defaultValue = param.defaultValue;
1264
- existingParam.resolver = param.resolver || existingParam.resolver;
1265
- this.paramMap[param.name] = existingParam;
1266
- }
1267
- resolveValue(param, alreadyResolved) {
1268
- const envName = param.name.replace(/\.?([A-Z|0-9]+)/g, function (x, y) {
1269
- return "_" + y.toLowerCase();
1270
- }).replace(/\./gi, "_").replace(/^_/, "").toUpperCase();
1271
- const envValue = process.env[envName];
1272
- const helper = (p) => this.resolveInternal(p, alreadyResolved);
1273
- if (typeof envValue !== "undefined") {
1274
- const value = isFunction(param.resolver)
1275
- ? param.resolver(envValue, helper)
1276
- : convertValue(envValue, getType(param.defaultValue));
1277
- console.log(colorize(`Processing param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), colorize(envName, ConsoleColor.FgBlue), `"${envValue}"`, value);
1278
- return value;
1279
- }
1280
- else if (isFunction(param.resolver)) {
1281
- const value = param.resolver(param.defaultValue, helper);
1282
- console.log(colorize(`Processing default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue, value);
1283
- return value;
1284
- }
1285
- console.log(colorize(`Using default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue);
1286
- return param.defaultValue;
1287
- }
1288
- hasParam(name) {
1289
- return !!this.paramMap[name];
1290
- }
1291
- resolve(name) {
1292
- return this.resolveInternal(name, []);
1293
- }
1294
- resolveInternal(name, alreadyResolved) {
1295
- if (alreadyResolved.includes(name)) {
1296
- throw new Error(`Circular dependency detected: ${alreadyResolved.join(" -> ")} -> ${name}`);
1297
- }
1298
- alreadyResolved.push(name);
1299
- const param = this.paramMap[name];
1300
- if (!param)
1301
- throw new Error(`Parameter with name: '${name}' does not exists in configuration`);
1302
- if (!(name in this.paramValues)) {
1303
- this.paramValues[name] = this.resolveValue(param, alreadyResolved);
1304
- }
1305
- return this.paramValues[name];
1306
- }
1307
- };
1308
- Configuration = __decorate([
1309
- singleton(),
1310
- __param(0, injectAll(PARAMETER))
1311
- ], Configuration);
1312
-
1313
- let EndpointProvider = class EndpointProvider {
1314
- configure(app) {
1315
- return __awaiter(this, void 0, void 0, function* () {
1316
- console.log(`Express app is mounted to: ${app.mountpath}`);
1317
- });
1318
- }
1319
- };
1320
- EndpointProvider = __decorate([
1321
- injectable(),
1322
- scoped(Lifecycle.ContainerScoped)
1323
- ], EndpointProvider);
1324
-
1325
- let Fixtures = class Fixtures {
1326
- constructor(fixtures) {
1327
- this.fixtures = fixtures;
1328
- }
1329
- load(output) {
1330
- return __awaiter(this, void 0, void 0, function* () {
1331
- if (!this.fixtures)
1332
- return;
1333
- output = output || {
1334
- write: console.log,
1335
- writeln: t => console.log(t + "\n")
1336
- };
1337
- for (let fixture of this.fixtures) {
1338
- yield fixture.load(output);
1339
- }
1340
- });
1341
- }
1342
- };
1343
- Fixtures = __decorate([
1344
- injectable(),
1345
- scoped(Lifecycle.ContainerScoped),
1346
- __param(0, injectAll(FIXTURE))
1347
- ], Fixtures);
1348
-
1349
- const sharp$1 = sharp_;
1350
- let Gallery = class Gallery {
1351
- constructor(config, galleryCache) {
1352
- this.config = config;
1353
- this.galleryCache = galleryCache;
1354
- this.cache = {};
1355
- this.dir = this.config.resolve("galleryDir");
1356
- this.output = join(this.config.resolve("cacheDir"), "gallery");
1357
- }
1358
- getFolder(folder, size = null) {
1359
- return __awaiter(this, void 0, void 0, function* () {
1360
- this.cache[folder] = this.cache[folder] || new Promise(resolve => {
1361
- lstat(join(this.dir, folder), (err, stats) => {
1362
- if (err || !stats.isDirectory()) {
1363
- resolve([]);
1364
- return;
1365
- }
1366
- this.readRecursive(folder, "", size).then(resolve, () => resolve([]));
1367
- });
1368
- });
1369
- return this.cache[folder];
1370
- });
1371
- }
1372
- readRecursive(path, folder, size) {
1373
- return new Promise(resolve => {
1374
- readdir(join(this.dir, path), (err, files) => {
1375
- if (err) {
1376
- resolve([]);
1377
- return;
1378
- }
1379
- const promises = files.map(file => {
1380
- return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
1381
- const filePath = join(path, file);
1382
- const absoluteFilePath = join(this.dir, filePath);
1383
- lstat(absoluteFilePath, (err, stats) => {
1384
- if (err) {
1385
- resolve([]);
1386
- return;
1387
- }
1388
- if (stats.isDirectory()) {
1389
- this.readRecursive(filePath, join(folder, file), size).then(resolve);
1390
- return;
1391
- }
1392
- const sharpImg = sharp$1(absoluteFilePath);
1393
- sharpImg.rotate().metadata().then(() => {
1394
- const getResultPath = (isThumb) => {
1395
- return join(this.output, filePath.replace(/.([a-z|A-Z]+)$/gi, function (ext) {
1396
- const suffix = isThumb ? 'thumb' : 'big';
1397
- return `-${suffix}${ext}`;
1398
- }));
1399
- };
1400
- resolve([this.galleryCache.create(folder, size, {
1401
- getOriginal: () => {
1402
- return new Promise((res, rej) => {
1403
- readFile$1(absoluteFilePath, (err, data) => {
1404
- if (err) {
1405
- rej(err);
1406
- return;
1407
- }
1408
- res(data);
1409
- });
1410
- });
1411
- },
1412
- writeResult: (isThumb, buffer) => {
1413
- return new Promise((res, rej) => __awaiter(this, void 0, void 0, function* () {
1414
- const resultPath = getResultPath(isThumb);
1415
- yield mkdirRecursive(dirname(resultPath));
1416
- writeFile$1(resultPath, buffer, err => {
1417
- if (err) {
1418
- rej(err);
1419
- return;
1420
- }
1421
- res();
1422
- });
1423
- }));
1424
- },
1425
- hasResult: (isThumb) => {
1426
- return new Promise(res => {
1427
- access(getResultPath(isThumb), constants.R_OK, err => {
1428
- res(!err);
1429
- });
1430
- });
1431
- },
1432
- serveResult: (isThumb) => {
1433
- return new Promise((res, rej) => {
1434
- readFile$1(getResultPath(isThumb), (err, data) => {
1435
- if (err) {
1436
- rej(err);
1437
- return;
1438
- }
1439
- res(data);
1440
- });
1441
- });
1442
- }
1443
- })]);
1444
- }, () => resolve([]));
1445
- });
1446
- }));
1447
- });
1448
- Promise.all(promises).then(folders => {
1449
- resolve([].concat.apply([], folders));
1450
- });
1451
- });
1452
- });
1453
- }
1454
- };
1455
- Gallery = __decorate([
1456
- injectable(),
1457
- scoped(Lifecycle.ContainerScoped)
1458
- ], Gallery);
1459
-
1460
- const sharp = sharp_;
1461
- const bigSize = 1500;
1462
- const thumbSize = 250;
1463
- class GalleryImage {
1464
- constructor(folder, size, handler) {
1465
- this.folder = folder;
1466
- this.handler = handler;
1467
- this.thumb = v4();
1468
- this.big = v4();
1469
- this.targetSize = !size ? { width: thumbSize, height: thumbSize } : size;
1470
- }
1471
- serve(id) {
1472
- return __awaiter(this, void 0, void 0, function* () {
1473
- const isThumb = id == this.thumb;
1474
- if (yield this.handler.hasResult(isThumb)) {
1475
- return this.handler.serveResult(isThumb);
1476
- }
1477
- const original = sharp(yield this.handler.getOriginal()).rotate();
1478
- const meta = yield original.metadata();
1479
- const ratio = meta.width / meta.height;
1480
- const sizeRatio = isThumb ? this.targetSize.width / this.targetSize.height : 1;
1481
- const size = isThumb ? Math.max(this.targetSize.width, this.targetSize.height) : bigSize;
1482
- const targetHeight = ratio > sizeRatio ? size : Math.round(size / ratio);
1483
- const targetWidth = Math.round(targetHeight * ratio);
1484
- const resized = original.resize(targetWidth, targetHeight);
1485
- const buffer = yield (isThumb ? resized.extract({
1486
- left: Math.floor((targetWidth - this.targetSize.width) / 2),
1487
- top: Math.floor((targetHeight - this.targetSize.height) / 2),
1488
- width: this.targetSize.width,
1489
- height: this.targetSize.height
1490
- }).toBuffer() : resized.toBuffer());
1491
- yield this.handler.writeResult(isThumb, buffer);
1492
- return this.handler.serveResult(isThumb);
1493
- });
1494
- }
1495
- }
1496
-
1497
- let GalleryCache = class GalleryCache {
1498
- constructor() {
1499
- this.imgCache = {};
1500
- }
1501
- put(img) {
1502
- this.imgCache[img.thumb] = img;
1503
- this.imgCache[img.big] = img;
1504
- }
1505
- serve(id) {
1506
- const img = this.imgCache[id];
1507
- return !img ? null : img.serve(id);
1508
- }
1509
- create(folder, targetSize, handler) {
1510
- const image = new GalleryImage(folder, targetSize, handler);
1511
- this.put(image);
1512
- return image;
1513
- }
1514
- };
1515
- GalleryCache = __decorate([
1516
- injectable(),
1517
- scoped(Lifecycle.ContainerScoped)
1518
- ], GalleryCache);
1519
-
1520
- let IdGenerator = class IdGenerator {
1296
+ let Logger = class Logger {
1521
1297
  constructor(config) {
1522
1298
  this.config = config;
1523
- this.prefix = config.resolve("idPrefix");
1524
- this.separator = config.resolve("idSeparator");
1525
- this.chars = config.resolve("idChars");
1526
- this.parts = config.resolve("idParts");
1527
- }
1528
- generate(checkCb) {
1529
- return __awaiter(this, void 0, void 0, function* () {
1530
- let id = null;
1531
- let tries = 0;
1532
- let notGood = true;
1533
- while (notGood && tries < 5) {
1534
- id = this.generateId();
1535
- notGood = yield checkCb(id);
1536
- tries++;
1537
- }
1538
- if (notGood) {
1539
- throw `Couldn't generate an unique id..`;
1540
- }
1541
- return id;
1542
- });
1299
+ this.tags = this.config.resolve("logTags");
1300
+ this.ignoredTags = this.config.resolve("ignoredLogTags");
1543
1301
  }
1544
- generateId() {
1545
- return this.prefix + this.parts.map(num => {
1546
- let s = "";
1547
- for (let i = 0; i < num; i++) {
1548
- const ix = rand(0, this.chars.length - 1);
1549
- s += this.chars[ix];
1550
- }
1551
- return s;
1552
- }).join(this.separator);
1302
+ log(tag, ...params) {
1303
+ if (this.ignoredTags.includes(tag))
1304
+ return;
1305
+ if (this.tags.length === 0 || this.tags.includes(tag)) {
1306
+ console.log(`[${tag}]`, ...params);
1307
+ }
1553
1308
  }
1554
1309
  };
1555
- IdGenerator = __decorate([
1556
- injectable(),
1557
- scoped(Lifecycle.ContainerScoped)
1558
- ], IdGenerator);
1310
+ Logger = __decorate([
1311
+ singleton(),
1312
+ __metadata("design:paramtypes", [Configuration])
1313
+ ], Logger);
1559
1314
 
1560
1315
  let JobManager = class JobManager {
1561
1316
  constructor(config, logger, container, jobTypes) {
@@ -1741,86 +1496,306 @@ JobManager = __decorate([
1741
1496
  injectable(),
1742
1497
  scoped(Lifecycle.ContainerScoped),
1743
1498
  __param(2, inject(DI_CONTAINER)),
1744
- __param(3, injectAll(JOB))
1499
+ __param(3, injectAll(JOB)),
1500
+ __metadata("design:paramtypes", [Configuration,
1501
+ Logger, Object, Array])
1745
1502
  ], JobManager);
1746
1503
 
1747
- class LazyAsset extends BaseEntity {
1748
- constructor(id, data, collection, logger, assets, progresses) {
1504
+ class Progress extends BaseEntity {
1505
+ constructor(id, data, collection) {
1749
1506
  super(id, data, collection);
1750
- this.logger = logger;
1751
- this.assets = assets;
1752
- this.progresses = progresses;
1753
1507
  }
1754
- get jobName() {
1755
- return this.data.jobName;
1508
+ get current() {
1509
+ return this.data.current;
1510
+ }
1511
+ get max() {
1512
+ return this.data.max;
1513
+ }
1514
+ get message() {
1515
+ return this.data.message;
1516
+ }
1517
+ get error() {
1518
+ return this.data.error;
1519
+ }
1520
+ get canceled() {
1521
+ return this.data.canceled;
1522
+ }
1523
+ get percent() {
1524
+ return this.max > 0 ? Math.round(this.current / this.max * 100) : 0;
1525
+ }
1526
+ get remaining() {
1527
+ return this.max > 0 ? this.max - this.current : 0;
1528
+ }
1529
+ setMessageBridge(messageBridge) {
1530
+ this.messageBridge = messageBridge || this.messageBridge;
1531
+ return this;
1532
+ }
1533
+ createSubProgress(progressValue, max, message) {
1534
+ return __awaiter(this, void 0, void 0, function* () {
1535
+ if (max <= 0 && progressValue > 0) {
1536
+ yield this.advance(progressValue);
1537
+ }
1538
+ if (message !== null) {
1539
+ this.data.message = message;
1540
+ yield this.save();
1541
+ }
1542
+ return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1543
+ });
1544
+ }
1545
+ setMax(max) {
1546
+ return __awaiter(this, void 0, void 0, function* () {
1547
+ if (isNaN(max) || max <= 0) {
1548
+ throw "Max progress value must be bigger than zero";
1549
+ }
1550
+ this.data.max = max;
1551
+ yield this.save();
1552
+ });
1553
+ }
1554
+ setMessage(message) {
1555
+ return __awaiter(this, void 0, void 0, function* () {
1556
+ this.data.message = message;
1557
+ yield this.save();
1558
+ });
1559
+ }
1560
+ setError(error) {
1561
+ return __awaiter(this, void 0, void 0, function* () {
1562
+ this.data.error = error;
1563
+ yield this.save();
1564
+ });
1565
+ }
1566
+ advance(value = 1) {
1567
+ return __awaiter(this, void 0, void 0, function* () {
1568
+ if (isNaN(value) || value <= 0) {
1569
+ throw new Error(`Advance value must be bigger than zero: ${this.id}`);
1570
+ }
1571
+ yield this.load();
1572
+ if (this.deleted || this.canceled) {
1573
+ const status = this.deleted ? "deleted" : "canceled";
1574
+ throw new Error(`Can't advance ${status} progress: ${this.id}`);
1575
+ }
1576
+ this.data.current = Math.min(this.max, this.current + value);
1577
+ yield this.save();
1578
+ });
1579
+ }
1580
+ cancel() {
1581
+ return __awaiter(this, void 0, void 0, function* () {
1582
+ this.data.canceled = true;
1583
+ yield this.save();
1584
+ });
1585
+ }
1586
+ save() {
1587
+ if (this.messageBridge) {
1588
+ this.messageBridge.sendMessage(`progress-changed`, this.toJSON());
1589
+ }
1590
+ return super.save();
1591
+ }
1592
+ }
1593
+ class SubProgress {
1594
+ constructor(parent, progressFrom, progressValue, mMax = 100) {
1595
+ this.parent = parent;
1596
+ this.progressFrom = progressFrom;
1597
+ this.progressValue = progressValue;
1598
+ this.mMax = mMax;
1599
+ if (progressFrom < 0) {
1600
+ throw "Progress from must be bigger than or zero";
1601
+ }
1602
+ if (progressValue <= 0) {
1603
+ throw "Progress value must be bigger than zero";
1604
+ }
1605
+ this.mCurrent = 0;
1606
+ }
1607
+ get id() {
1608
+ return this.parent.id;
1609
+ }
1610
+ get current() {
1611
+ return this.mCurrent;
1612
+ }
1613
+ get max() {
1614
+ return this.mMax;
1615
+ }
1616
+ get message() {
1617
+ return this.parent.message;
1618
+ }
1619
+ get error() {
1620
+ return this.parent.error;
1621
+ }
1622
+ get percent() {
1623
+ return this.parent.percent;
1624
+ }
1625
+ get remaining() {
1626
+ return this.max - this.mCurrent;
1627
+ }
1628
+ get canceled() {
1629
+ return !this.parent || this.parent.canceled;
1630
+ }
1631
+ setMessageBridge(messageBridge) {
1632
+ if (!this.parent)
1633
+ return this;
1634
+ this.parent.setMessageBridge(messageBridge);
1635
+ return this;
1636
+ }
1637
+ createSubProgress(progressValue, max, message) {
1638
+ return __awaiter(this, void 0, void 0, function* () {
1639
+ if (max <= 0 && progressValue > 0) {
1640
+ yield this.advance(progressValue);
1641
+ }
1642
+ if (message !== null) {
1643
+ yield this.setMessage(message);
1644
+ }
1645
+ return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1646
+ });
1647
+ }
1648
+ setMax(max) {
1649
+ return __awaiter(this, void 0, void 0, function* () {
1650
+ if (isNaN(max) || max <= 0) {
1651
+ throw "Max progress value must be bigger than zero";
1652
+ }
1653
+ this.mMax = max;
1654
+ yield this.save();
1655
+ });
1656
+ }
1657
+ setMessage(message) {
1658
+ return __awaiter(this, void 0, void 0, function* () {
1659
+ if (!this.parent)
1660
+ return null;
1661
+ yield this.parent.setMessage(message);
1662
+ });
1663
+ }
1664
+ setError(error) {
1665
+ return __awaiter(this, void 0, void 0, function* () {
1666
+ if (!this.parent)
1667
+ return null;
1668
+ yield this.parent.setError(error);
1669
+ });
1670
+ }
1671
+ advance(value = 1) {
1672
+ return __awaiter(this, void 0, void 0, function* () {
1673
+ if (isNaN(value) || value <= 0) {
1674
+ throw "Advance value must be bigger than zero";
1675
+ }
1676
+ this.mCurrent = Math.min(this.max, this.mCurrent + value);
1677
+ yield this.save();
1678
+ });
1679
+ }
1680
+ cancel() {
1681
+ return __awaiter(this, void 0, void 0, function* () {
1682
+ if (!this.parent)
1683
+ return null;
1684
+ yield this.parent.cancel();
1685
+ });
1686
+ }
1687
+ save() {
1688
+ return __awaiter(this, void 0, void 0, function* () {
1689
+ const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
1690
+ const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
1691
+ const current = this.parent.current;
1692
+ if (newProgress <= current)
1693
+ return null;
1694
+ yield this.parent.advance(newProgress);
1695
+ });
1756
1696
  }
1757
- get jobParams() {
1758
- return this.data.jobParams;
1697
+ load() {
1698
+ return __awaiter(this, void 0, void 0, function* () {
1699
+ return null;
1700
+ });
1759
1701
  }
1760
- get jobQue() {
1761
- return this.data.jobQue;
1702
+ toJSON() {
1703
+ return this.parent.toJSON();
1762
1704
  }
1763
- get progressId() {
1764
- return this.data.progressId;
1705
+ }
1706
+
1707
+ let Progresses = class Progresses {
1708
+ constructor(connector, jobMan) {
1709
+ this.connector = connector;
1710
+ this.jobMan = jobMan;
1711
+ this.collection = connector.database.collection("progresses");
1712
+ this.progresses = {};
1713
+ this.jobMan.on("progress-changed", progress => {
1714
+ const id = progress.id;
1715
+ this.progresses[id] = new Progress(new ObjectId$1(id), progress, this.collection);
1716
+ });
1765
1717
  }
1766
- get assetId() {
1767
- return this.data.assetId;
1718
+ waitToFinish(id) {
1719
+ return __awaiter(this, void 0, void 0, function* () {
1720
+ return Promise.race([
1721
+ this.waitForProgress(id, () => __awaiter(this, void 0, void 0, function* () {
1722
+ let progress = this.progresses[id];
1723
+ if (!progress || progress.percent < 100) {
1724
+ progress = yield this.get(id);
1725
+ }
1726
+ if (!progress) {
1727
+ throw new Error(`Progress does not exists with id: ${id}`);
1728
+ }
1729
+ return progress;
1730
+ }), 500),
1731
+ this.waitForProgress(id, () => __awaiter(this, void 0, void 0, function* () {
1732
+ return this.progresses[id] || null;
1733
+ }), 25)
1734
+ ]);
1735
+ });
1768
1736
  }
1769
- unlink() {
1737
+ get(id) {
1770
1738
  return __awaiter(this, void 0, void 0, function* () {
1771
- yield this.load();
1772
- if (!this.progressId) {
1773
- yield this.collection.deleteOne({ _id: this.mId });
1774
- }
1775
- return deleteFromBucket(this.assets.bucket, new ObjectId$1(this.assetId));
1739
+ return !id ? null : this.find({ _id: new ObjectId$1(id) });
1776
1740
  });
1777
1741
  }
1778
- startWorking() {
1779
- this.load().then(() => {
1780
- if (this.deleted)
1781
- return;
1782
- this.progresses.get(this.progressId).then(p => {
1783
- p === null || p === void 0 ? void 0 : p.cancel();
1784
- });
1785
- this.startWorkingOnAsset(false).then(() => {
1786
- this.logger.log("lazy-assets", `Started working on lazy asset: ${this.id}`);
1787
- }).catch(reason => {
1788
- this.logger.log("lazy-assets", `Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1789
- });
1742
+ find(where) {
1743
+ return __awaiter(this, void 0, void 0, function* () {
1744
+ const data = yield this.collection.findOne(where);
1745
+ return !data ? null : new Progress(data._id, data, this.collection);
1790
1746
  });
1791
1747
  }
1792
- loadAsset() {
1748
+ create(max = 100) {
1793
1749
  return __awaiter(this, void 0, void 0, function* () {
1794
- yield this.load();
1795
- if (this.deleted)
1796
- return null;
1797
- if (this.assetId) {
1798
- return this.assets.read(this.assetId);
1799
- }
1800
- if (this.progressId) {
1801
- yield this.progresses.waitToFinish(this.progressId);
1802
- return this.loadAsset();
1750
+ if (isNaN(max) || max <= 0) {
1751
+ throw new Error(`Max progress value must be bigger than zero`);
1803
1752
  }
1804
- yield this.startWorkingOnAsset(true);
1805
- return this.loadAsset();
1753
+ const data = {
1754
+ current: 0,
1755
+ max: max,
1756
+ message: "",
1757
+ error: "",
1758
+ canceled: false
1759
+ };
1760
+ const res = yield this.collection.insertOne(data);
1761
+ return new Progress(res.insertedId, data, this.collection);
1806
1762
  });
1807
1763
  }
1808
- writeAsset(asset) {
1764
+ remove(id) {
1809
1765
  return __awaiter(this, void 0, void 0, function* () {
1810
- this.data.assetId = asset.id;
1811
- yield this.save();
1812
- return asset;
1766
+ yield this.collection.deleteOne({ _id: new ObjectId$1(id) });
1767
+ return id;
1813
1768
  });
1814
1769
  }
1815
- startWorkingOnAsset(fromLoad) {
1770
+ waitForProgress(id, cb, delay) {
1816
1771
  return __awaiter(this, void 0, void 0, function* () {
1817
- this.data.progressId = (yield this.progresses.create()).id;
1818
- this.data.assetId = null;
1819
- yield this.save();
1820
- yield this.progresses.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id, fromLoad }));
1772
+ let isFinished = false;
1773
+ let progress = null;
1774
+ let waitTime = 0;
1775
+ while (!isFinished) {
1776
+ progress = yield cb();
1777
+ waitTime += delay;
1778
+ if (progress) {
1779
+ if (progress.error) {
1780
+ throw new Error(progress.error);
1781
+ }
1782
+ isFinished = progress.percent >= 100;
1783
+ }
1784
+ if (!isFinished) {
1785
+ if (waitTime >= this.jobMan.maxTimeout) {
1786
+ throw new Error(`Progress with id: ${id} probably never will be finished!`);
1787
+ }
1788
+ yield promiseTimeout(delay);
1789
+ }
1790
+ }
1791
+ return progress;
1821
1792
  });
1822
1793
  }
1823
- }
1794
+ };
1795
+ Progresses = __decorate([
1796
+ singleton(),
1797
+ __metadata("design:paramtypes", [MongoConnector, JobManager])
1798
+ ], Progresses);
1824
1799
 
1825
1800
  let LazyAssets = class LazyAssets {
1826
1801
  constructor(connector, assets, progresses, logger, jobMan) {
@@ -1856,613 +1831,505 @@ let LazyAssets = class LazyAssets {
1856
1831
  const data = yield this.collection.findOne(where);
1857
1832
  return !data
1858
1833
  ? null
1859
- : new LazyAsset(data._id, data, this.collection, this.logger, this.assets, this.progresses);
1860
- });
1861
- }
1862
- unlink(id) {
1863
- return __awaiter(this, void 0, void 0, function* () {
1864
- const asset = yield this.read(id);
1865
- if (!asset)
1866
- return null;
1867
- return asset.unlink();
1868
- });
1869
- }
1870
- };
1871
- LazyAssets = __decorate([
1872
- injectable(),
1873
- scoped(Lifecycle.ContainerScoped)
1874
- ], LazyAssets);
1875
-
1876
- let Logger = class Logger {
1877
- constructor(config) {
1878
- this.config = config;
1879
- this.tags = this.config.resolve("logTags");
1880
- this.ignoredTags = this.config.resolve("ignoredLogTags");
1881
- }
1882
- log(tag, ...params) {
1883
- if (this.ignoredTags.includes(tag))
1884
- return;
1885
- if (this.tags.length === 0 || this.tags.includes(tag)) {
1886
- console.log(`[${tag}]`, ...params);
1887
- }
1888
- }
1889
- };
1890
- Logger = __decorate([
1891
- singleton()
1892
- ], Logger);
1893
-
1894
- let MailSender = class MailSender {
1895
- constructor(config, renderer) {
1896
- this.config = config;
1897
- this.renderer = renderer;
1898
- this.transporter = createTransport({
1899
- host: this.config.resolve("smtpHost"),
1900
- port: this.config.resolve("smtpPort"),
1901
- auth: {
1902
- user: this.config.resolve("smtpUser"),
1903
- pass: this.config.resolve("smtpPassword"),
1904
- }
1905
- });
1906
- }
1907
- get translator() {
1908
- return this.renderer.translator;
1909
- }
1910
- sendMail(language, options) {
1911
- return __awaiter(this, void 0, void 0, function* () {
1912
- const subject = yield this.translator.getTranslation(language, options.subject || "-");
1913
- const html = yield this.renderer.render(options.template, language, options.context);
1914
- return this.transporter.sendMail({
1915
- from: options.from || this.config.resolve("mailSenderAddress"),
1916
- to: options.to,
1917
- attachments: options.attachments,
1918
- subject,
1919
- html
1920
- });
1921
- });
1922
- }
1923
- };
1924
- MailSender = __decorate([
1925
- singleton()
1926
- ], MailSender);
1927
-
1928
- let MemoryCache = class MemoryCache {
1929
- constructor(cache) {
1930
- this.cache = cache;
1931
- this.cacheMap = new Map();
1932
- }
1933
- set(key, value, ttl, expirationTimestamp = null, tags = {}) {
1934
- return __awaiter(this, void 0, void 0, function* () {
1935
- const now = Math.round(new Date().getTime() / 1000);
1936
- const expTimestamp = Math.min(isNaN(ttl) ? Number.MAX_SAFE_INTEGER : ttl, 3600);
1937
- this.cacheMap.set(key, {
1938
- _id: key,
1939
- data: value,
1940
- expirationTimestamp: expTimestamp,
1941
- expiresAt: now + expTimestamp,
1942
- });
1943
- return this.cache.set(key, value, ttl, expirationTimestamp, tags);
1944
- });
1945
- }
1946
- get(key) {
1947
- return __awaiter(this, void 0, void 0, function* () {
1948
- let item = this.cacheMap.get(key);
1949
- const now = Math.round(new Date().getTime() / 1000);
1950
- let expTimestamp = 3600;
1951
- if (item && item.expiresAt && item.expiresAt < now) {
1952
- expTimestamp = item.expirationTimestamp;
1953
- item = null;
1954
- }
1955
- if (!item) {
1956
- const value = yield this.cache.get(key);
1957
- this.cacheMap.set(key, {
1958
- _id: key,
1959
- data: value,
1960
- expirationTimestamp: expTimestamp,
1961
- expiresAt: now + expTimestamp,
1962
- });
1963
- return value;
1964
- }
1965
- return item.data;
1966
- });
1967
- }
1968
- getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
1969
- return __awaiter(this, void 0, void 0, function* () {
1970
- try {
1971
- return yield this.get(key);
1972
- }
1973
- catch (e) {
1974
- return yield this.set(key, yield valueCb(), ttl, expirationTimestamp, tags);
1975
- }
1834
+ : new LazyAsset(data._id, data, this.collection, this.logger, this.assets, this.progresses);
1976
1835
  });
1977
1836
  }
1978
- delete(key) {
1837
+ unlink(id) {
1979
1838
  return __awaiter(this, void 0, void 0, function* () {
1980
- this.cacheMap.delete(key);
1981
- yield this.cacheMap.delete(key);
1839
+ const asset = yield this.read(id);
1840
+ if (!asset)
1841
+ return null;
1842
+ return asset.unlink();
1982
1843
  });
1983
1844
  }
1984
1845
  };
1985
- MemoryCache = __decorate([
1846
+ LazyAssets = __decorate([
1986
1847
  injectable(),
1987
- scoped(Lifecycle.ContainerScoped)
1988
- ], MemoryCache);
1848
+ scoped(Lifecycle.ContainerScoped),
1849
+ __metadata("design:paramtypes", [MongoConnector,
1850
+ Assets,
1851
+ Progresses,
1852
+ Logger,
1853
+ JobManager])
1854
+ ], LazyAssets);
1989
1855
 
1990
- let MongoConnector = class MongoConnector {
1991
- constructor(configuration) {
1992
- this.configuration = configuration;
1993
- this.conn = null;
1994
- this.db = null;
1995
- this.fsBucket = null;
1996
- }
1997
- get connection() {
1998
- return this.conn;
1999
- }
2000
- get database() {
2001
- return this.db;
2002
- }
2003
- get bucket() {
2004
- return this.fsBucket;
1856
+ let AssetResolver = class AssetResolver {
1857
+ constructor(assets, lazyAssets) {
1858
+ this.assets = assets;
1859
+ this.lazyAssets = lazyAssets;
2005
1860
  }
2006
- connect() {
1861
+ resolve(id, lazy = false) {
2007
1862
  return __awaiter(this, void 0, void 0, function* () {
2008
- if (this.db)
2009
- return this.db;
2010
- this.conn = (yield connect(this.configuration.resolve("mongoUri"), {
2011
- dbName: this.configuration.resolve("mongoDb"),
2012
- user: this.configuration.resolve("mongoUser"),
2013
- pass: this.configuration.resolve("mongoPassword")
2014
- })).connection;
2015
- this.db = this.conn.db;
2016
- this.fsBucket = new GridFSBucket(this.db, { bucketName: "assets" });
2017
- });
2018
- }
2019
- };
2020
- MongoConnector = __decorate([
2021
- singleton()
2022
- ], MongoConnector);
2023
-
2024
- function checkValue(multi, value) {
2025
- if (multi) {
2026
- return Array.isArray(value) && value.every(v => {
2027
- try {
2028
- const id = new ObjectId$1(v);
2029
- return id instanceof ObjectId$1;
1863
+ let asset = null;
1864
+ if (lazy) {
1865
+ const lazyAsset = yield this.lazyAssets.read(id);
1866
+ if (!lazyAsset)
1867
+ return null;
1868
+ return lazyAsset.loadAsset();
2030
1869
  }
2031
- catch (e) {
2032
- return false;
1870
+ asset = yield this.assets.read(id);
1871
+ if (!asset) {
1872
+ const lazyAsset = yield this.lazyAssets.read(id);
1873
+ if (!lazyAsset)
1874
+ return null;
1875
+ return lazyAsset.loadAsset();
2033
1876
  }
1877
+ return asset;
2034
1878
  });
2035
1879
  }
2036
- if (null === value)
2037
- return true;
2038
- try {
2039
- const id = new ObjectId$1(value);
2040
- return id instanceof ObjectId$1;
2041
- }
2042
- catch (e) {
2043
- return false;
2044
- }
2045
- }
2046
- let IsFile = class IsFile {
2047
- validate(value, validationArguments) {
2048
- const [multi] = (validationArguments.constraints || []);
2049
- return checkValue(multi, value);
2050
- }
2051
- };
2052
- IsFile = __decorate([
2053
- ValidatorConstraint()
2054
- ], IsFile);
2055
- let IsObjectId = class IsObjectId {
2056
- validate(value, validationArguments) {
2057
- const [_, multi] = (validationArguments.constraints || []);
2058
- return checkValue(multi, value);
2059
- }
2060
1880
  };
2061
- IsObjectId = __decorate([
2062
- ValidatorConstraint()
2063
- ], IsObjectId);
1881
+ AssetResolver = __decorate([
1882
+ injectable(),
1883
+ scoped(Lifecycle.ContainerScoped),
1884
+ __metadata("design:paramtypes", [Assets, LazyAssets])
1885
+ ], AssetResolver);
2064
1886
 
2065
- let OpenApi = class OpenApi {
2066
- constructor(container, customValidation) {
2067
- this.container = container;
2068
- this.customValidation = customValidation;
2069
- this.docs = null;
2070
- }
2071
- get apiDocs() {
2072
- if (!this.docs)
2073
- this.docs = this.createApiDocs();
2074
- return this.docs;
1887
+ const express = express_;
1888
+ let BackendProvider = class BackendProvider {
1889
+ constructor() {
1890
+ this.express = express();
1891
+ this.express.set("trust proxy", true);
1892
+ this.server = createServer(this.express);
2075
1893
  }
2076
- get apiDocsStr() {
2077
- if (!this.docsStr)
2078
- this.docsStr = JSON.stringify(this.apiDocs);
2079
- return this.docsStr;
1894
+ get io() {
1895
+ this.ioServer = this.ioServer || new Server(this.server, { path: "/socket" });
1896
+ return this.ioServer;
2080
1897
  }
2081
- schemaToExample(src, req) {
2082
- var _a, _b, _c;
1898
+ };
1899
+ BackendProvider = __decorate([
1900
+ singleton(),
1901
+ __metadata("design:paramtypes", [])
1902
+ ], BackendProvider);
1903
+
1904
+ let CacheProcessor = class CacheProcessor {
1905
+ serialize(data) {
2083
1906
  return __awaiter(this, void 0, void 0, function* () {
2084
- if (src.$ref) {
2085
- const schemas = this.apiDocs.components.schemas;
2086
- const schema = src.$ref
2087
- .replace("#/components/schemas/", "")
2088
- .replace("#/definitions/", "");
2089
- return this.schemaToExample(schemas[schema], req);
2090
- }
2091
- let schema = src;
2092
- if (schema.oneOf) {
2093
- schema = Object.assign({}, schema, schema.oneOf[0]);
2094
- }
2095
- if (schema.type === "object") {
2096
- const result = {};
2097
- yield Promise.all(Object.keys(schema.properties).map((key) => __awaiter(this, void 0, void 0, function* () {
2098
- result[key] = yield this.schemaToExample(schema.properties[key], req);
2099
- })));
2100
- return result;
2101
- }
2102
- if (schema.type === "array") {
2103
- return [yield this.schemaToExample(schema.items, req)];
2104
- }
2105
- if (schema.type === "string") {
2106
- if (isDefined(schema.default)) {
2107
- if (isFunction(schema.default)) {
2108
- return schema.default(this.container);
2109
- }
2110
- return schema.default;
2111
- }
2112
- if (schema.format == "date") {
2113
- return new Date().toISOString().substr(0, 10);
2114
- }
2115
- if (schema.format == "date-time") {
2116
- return new Date().toISOString();
2117
- }
2118
- if (schema.enum) {
2119
- return schema.enum[0];
2120
- }
2121
- return "string";
2122
- }
2123
- if (schema.type === "number") {
2124
- return (_a = schema.default) !== null && _a !== void 0 ? _a : 0;
2125
- }
2126
- else if (schema.type === "boolean") {
2127
- return (_b = schema.default) !== null && _b !== void 0 ? _b : false;
2128
- }
2129
- else {
2130
- return (_c = schema.default) !== null && _c !== void 0 ? _c : null;
2131
- }
1907
+ return data;
2132
1908
  });
2133
1909
  }
2134
- createApiDocs() {
2135
- const storage = getMetadataArgsStorage();
2136
- const docs = routingControllersToSpec(storage);
2137
- docs.basePath = "/api/";
2138
- docs.definitions = validationMetadatasToSchemas({
2139
- additionalConverters: {
2140
- [ValidationTypes.CUSTOM_VALIDATION]: (meta, options) => {
2141
- const res = isFunction(this.customValidation) ? this.customValidation(meta, options) : this.customValidation;
2142
- if (isObject(res))
2143
- return res;
2144
- const constraints = meta.constraints || [];
2145
- if (meta.constraintCls === IsFile) {
2146
- return {
2147
- multi: constraints[0] || false,
2148
- type: "file"
2149
- };
2150
- }
2151
- if (meta.constraintCls === IsObjectId) {
2152
- return {
2153
- endpoint: constraints[0] || false,
2154
- multi: constraints[1] || false,
2155
- type: "list"
2156
- };
2157
- }
2158
- return null;
2159
- }
2160
- }
1910
+ deserialize(data) {
1911
+ return __awaiter(this, void 0, void 0, function* () {
1912
+ return data;
2161
1913
  });
2162
- docs.components.schemas = docs.definitions;
2163
- return docs;
2164
1914
  }
2165
1915
  };
2166
- OpenApi = __decorate([
2167
- singleton(),
2168
- __param(0, inject(DI_CONTAINER)),
2169
- __param(1, inject(OPENAPI_VALIDATION))
2170
- ], OpenApi);
1916
+ CacheProcessor = __decorate([
1917
+ injectable(),
1918
+ scoped(Lifecycle.ContainerScoped)
1919
+ ], CacheProcessor);
2171
1920
 
2172
- class Progress extends BaseEntity {
2173
- constructor(id, data, collection) {
2174
- super(id, data, collection);
2175
- }
2176
- get current() {
2177
- return this.data.current;
2178
- }
2179
- get max() {
2180
- return this.data.max;
2181
- }
2182
- get message() {
2183
- return this.data.message;
2184
- }
2185
- get error() {
2186
- return this.data.error;
2187
- }
2188
- get canceled() {
2189
- return this.data.canceled;
2190
- }
2191
- get percent() {
2192
- return this.max > 0 ? Math.round(this.current / this.max * 100) : 0;
2193
- }
2194
- get remaining() {
2195
- return this.max > 0 ? this.max - this.current : 0;
1921
+ let Cache = class Cache {
1922
+ constructor(connector, config, cacheProcessor) {
1923
+ this.connector = connector;
1924
+ this.config = config;
1925
+ this.cacheProcessor = cacheProcessor;
2196
1926
  }
2197
- setMessageBridge(messageBridge) {
2198
- this.messageBridge = messageBridge || this.messageBridge;
2199
- return this;
1927
+ prepare() {
1928
+ return __awaiter(this, void 0, void 0, function* () {
1929
+ if (this.collection)
1930
+ return;
1931
+ if (!this.connector.database) {
1932
+ throw new Error(`You can't use cache without mongo connection!`);
1933
+ }
1934
+ this.collection = this.connector.database.collection(this.config.resolve("cacheCollection"));
1935
+ yield this.collection.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
1936
+ });
2200
1937
  }
2201
- createSubProgress(progressValue, max, message) {
1938
+ set(key, value, ttl, expirationTimestamp = null, tags = {}) {
2202
1939
  return __awaiter(this, void 0, void 0, function* () {
2203
- if (max <= 0 && progressValue > 0) {
2204
- yield this.advance(progressValue);
1940
+ yield this.prepare();
1941
+ const item = {
1942
+ _id: key,
1943
+ data: yield this.cacheProcessor.serialize(value),
1944
+ tags: yield this.cacheProcessor.serialize(tags),
1945
+ expirationTimestamp,
1946
+ };
1947
+ if (ttl) {
1948
+ const now = Math.round(new Date().getTime() / 1000);
1949
+ item.expiresAt = now + ttl;
2205
1950
  }
2206
- if (message !== null) {
2207
- this.data.message = message;
2208
- yield this.save();
1951
+ yield this.collection.updateOne({ _id: key }, { $set: item }, { upsert: true });
1952
+ return value;
1953
+ });
1954
+ }
1955
+ get(key) {
1956
+ return __awaiter(this, void 0, void 0, function* () {
1957
+ yield this.prepare();
1958
+ let item = yield this.collection.findOne({ _id: key });
1959
+ const now = Math.round(new Date().getTime() / 1000);
1960
+ if (item && item.expiresAt && item.expiresAt < now) {
1961
+ item = null;
2209
1962
  }
2210
- return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
1963
+ if (!item) {
1964
+ throw new Error(`Cache probably doesn't exists with key: ${key}`);
1965
+ }
1966
+ return yield this.cacheProcessor.deserialize(item.data);
2211
1967
  });
2212
1968
  }
2213
- setMax(max) {
1969
+ getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
2214
1970
  return __awaiter(this, void 0, void 0, function* () {
2215
- if (isNaN(max) || max <= 0) {
2216
- throw "Max progress value must be bigger than zero";
1971
+ try {
1972
+ return yield this.get(key);
1973
+ }
1974
+ catch (e) {
1975
+ return yield this.set(key, yield valueCb(), ttl, expirationTimestamp, tags);
2217
1976
  }
2218
- this.data.max = max;
2219
- yield this.save();
2220
1977
  });
2221
1978
  }
2222
- setMessage(message) {
1979
+ delete(key) {
2223
1980
  return __awaiter(this, void 0, void 0, function* () {
2224
- this.data.message = message;
2225
- yield this.save();
1981
+ yield this.prepare();
1982
+ yield this.collection.deleteOne({ _id: key });
2226
1983
  });
2227
1984
  }
2228
- setError(error) {
1985
+ };
1986
+ Cache = __decorate([
1987
+ singleton(),
1988
+ __metadata("design:paramtypes", [MongoConnector, Configuration, CacheProcessor])
1989
+ ], Cache);
1990
+
1991
+ let EndpointProvider = class EndpointProvider {
1992
+ configure(app) {
2229
1993
  return __awaiter(this, void 0, void 0, function* () {
2230
- this.data.error = error;
2231
- yield this.save();
1994
+ console.log(`Express app is mounted to: ${app.mountpath}`);
2232
1995
  });
2233
1996
  }
2234
- advance(value = 1) {
1997
+ };
1998
+ EndpointProvider = __decorate([
1999
+ injectable(),
2000
+ scoped(Lifecycle.ContainerScoped)
2001
+ ], EndpointProvider);
2002
+
2003
+ let Fixtures = class Fixtures {
2004
+ constructor(fixtures) {
2005
+ this.fixtures = fixtures;
2006
+ }
2007
+ load(output) {
2235
2008
  return __awaiter(this, void 0, void 0, function* () {
2236
- if (isNaN(value) || value <= 0) {
2237
- throw new Error(`Advance value must be bigger than zero: ${this.id}`);
2009
+ if (!this.fixtures)
2010
+ return;
2011
+ output = output || {
2012
+ write: console.log,
2013
+ writeln: t => console.log(t + "\n")
2014
+ };
2015
+ for (let fixture of this.fixtures) {
2016
+ yield fixture.load(output);
2238
2017
  }
2239
- yield this.load();
2240
- if (this.deleted || this.canceled) {
2241
- const status = this.deleted ? "deleted" : "canceled";
2242
- throw new Error(`Can't advance ${status} progress: ${this.id}`);
2018
+ });
2019
+ }
2020
+ };
2021
+ Fixtures = __decorate([
2022
+ injectable(),
2023
+ scoped(Lifecycle.ContainerScoped),
2024
+ __param(0, injectAll(FIXTURE)),
2025
+ __metadata("design:paramtypes", [Array])
2026
+ ], Fixtures);
2027
+
2028
+ const sharp$1 = sharp_;
2029
+ const bigSize = 1500;
2030
+ const thumbSize = 250;
2031
+ class GalleryImage {
2032
+ constructor(folder, size, handler) {
2033
+ this.folder = folder;
2034
+ this.handler = handler;
2035
+ this.thumb = v4();
2036
+ this.big = v4();
2037
+ this.targetSize = !size ? { width: thumbSize, height: thumbSize } : size;
2038
+ }
2039
+ serve(id) {
2040
+ return __awaiter(this, void 0, void 0, function* () {
2041
+ const isThumb = id == this.thumb;
2042
+ if (yield this.handler.hasResult(isThumb)) {
2043
+ return this.handler.serveResult(isThumb);
2243
2044
  }
2244
- this.data.current = Math.min(this.max, this.current + value);
2245
- yield this.save();
2045
+ const original = sharp$1(yield this.handler.getOriginal()).rotate();
2046
+ const meta = yield original.metadata();
2047
+ const ratio = meta.width / meta.height;
2048
+ const sizeRatio = isThumb ? this.targetSize.width / this.targetSize.height : 1;
2049
+ const size = isThumb ? Math.max(this.targetSize.width, this.targetSize.height) : bigSize;
2050
+ const targetHeight = ratio > sizeRatio ? size : Math.round(size / ratio);
2051
+ const targetWidth = Math.round(targetHeight * ratio);
2052
+ const resized = original.resize(targetWidth, targetHeight);
2053
+ const buffer = yield (isThumb ? resized.extract({
2054
+ left: Math.floor((targetWidth - this.targetSize.width) / 2),
2055
+ top: Math.floor((targetHeight - this.targetSize.height) / 2),
2056
+ width: this.targetSize.width,
2057
+ height: this.targetSize.height
2058
+ }).toBuffer() : resized.toBuffer());
2059
+ yield this.handler.writeResult(isThumb, buffer);
2060
+ return this.handler.serveResult(isThumb);
2246
2061
  });
2247
2062
  }
2248
- cancel() {
2063
+ }
2064
+
2065
+ let GalleryCache = class GalleryCache {
2066
+ constructor() {
2067
+ this.imgCache = {};
2068
+ }
2069
+ put(img) {
2070
+ this.imgCache[img.thumb] = img;
2071
+ this.imgCache[img.big] = img;
2072
+ }
2073
+ serve(id) {
2074
+ const img = this.imgCache[id];
2075
+ return !img ? null : img.serve(id);
2076
+ }
2077
+ create(folder, targetSize, handler) {
2078
+ const image = new GalleryImage(folder, targetSize, handler);
2079
+ this.put(image);
2080
+ return image;
2081
+ }
2082
+ };
2083
+ GalleryCache = __decorate([
2084
+ injectable(),
2085
+ scoped(Lifecycle.ContainerScoped),
2086
+ __metadata("design:paramtypes", [])
2087
+ ], GalleryCache);
2088
+
2089
+ const sharp = sharp_;
2090
+ let Gallery = class Gallery {
2091
+ constructor(config, galleryCache) {
2092
+ this.config = config;
2093
+ this.galleryCache = galleryCache;
2094
+ this.cache = {};
2095
+ this.dir = this.config.resolve("galleryDir");
2096
+ this.output = join(this.config.resolve("cacheDir"), "gallery");
2097
+ }
2098
+ getFolder(folder, size = null) {
2249
2099
  return __awaiter(this, void 0, void 0, function* () {
2250
- this.data.canceled = true;
2251
- yield this.save();
2100
+ this.cache[folder] = this.cache[folder] || new Promise(resolve => {
2101
+ lstat(join(this.dir, folder), (err, stats) => {
2102
+ if (err || !stats.isDirectory()) {
2103
+ resolve([]);
2104
+ return;
2105
+ }
2106
+ this.readRecursive(folder, "", size).then(resolve, () => resolve([]));
2107
+ });
2108
+ });
2109
+ return this.cache[folder];
2110
+ });
2111
+ }
2112
+ readRecursive(path, folder, size) {
2113
+ return new Promise(resolve => {
2114
+ readdir(join(this.dir, path), (err, files) => {
2115
+ if (err) {
2116
+ resolve([]);
2117
+ return;
2118
+ }
2119
+ const promises = files.map(file => {
2120
+ return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
2121
+ const filePath = join(path, file);
2122
+ const absoluteFilePath = join(this.dir, filePath);
2123
+ lstat(absoluteFilePath, (err, stats) => {
2124
+ if (err) {
2125
+ resolve([]);
2126
+ return;
2127
+ }
2128
+ if (stats.isDirectory()) {
2129
+ this.readRecursive(filePath, join(folder, file), size).then(resolve);
2130
+ return;
2131
+ }
2132
+ const sharpImg = sharp(absoluteFilePath);
2133
+ sharpImg.rotate().metadata().then(() => {
2134
+ const getResultPath = (isThumb) => {
2135
+ return join(this.output, filePath.replace(/.([a-z|A-Z]+)$/gi, function (ext) {
2136
+ const suffix = isThumb ? 'thumb' : 'big';
2137
+ return `-${suffix}${ext}`;
2138
+ }));
2139
+ };
2140
+ resolve([this.galleryCache.create(folder, size, {
2141
+ getOriginal: () => {
2142
+ return new Promise((res, rej) => {
2143
+ readFile$1(absoluteFilePath, (err, data) => {
2144
+ if (err) {
2145
+ rej(err);
2146
+ return;
2147
+ }
2148
+ res(data);
2149
+ });
2150
+ });
2151
+ },
2152
+ writeResult: (isThumb, buffer) => {
2153
+ return new Promise((res, rej) => __awaiter(this, void 0, void 0, function* () {
2154
+ const resultPath = getResultPath(isThumb);
2155
+ yield mkdirRecursive(dirname(resultPath));
2156
+ writeFile$1(resultPath, buffer, err => {
2157
+ if (err) {
2158
+ rej(err);
2159
+ return;
2160
+ }
2161
+ res();
2162
+ });
2163
+ }));
2164
+ },
2165
+ hasResult: (isThumb) => {
2166
+ return new Promise(res => {
2167
+ access(getResultPath(isThumb), constants.R_OK, err => {
2168
+ res(!err);
2169
+ });
2170
+ });
2171
+ },
2172
+ serveResult: (isThumb) => {
2173
+ return new Promise((res, rej) => {
2174
+ readFile$1(getResultPath(isThumb), (err, data) => {
2175
+ if (err) {
2176
+ rej(err);
2177
+ return;
2178
+ }
2179
+ res(data);
2180
+ });
2181
+ });
2182
+ }
2183
+ })]);
2184
+ }, () => resolve([]));
2185
+ });
2186
+ }));
2187
+ });
2188
+ Promise.all(promises).then(folders => {
2189
+ resolve([].concat.apply([], folders));
2190
+ });
2191
+ });
2252
2192
  });
2253
2193
  }
2254
- save() {
2255
- if (this.messageBridge) {
2256
- this.messageBridge.sendMessage(`progress-changed`, this.toJSON());
2257
- }
2258
- return super.save();
2259
- }
2260
- }
2261
- class SubProgress {
2262
- constructor(parent, progressFrom, progressValue, mMax = 100) {
2263
- this.parent = parent;
2264
- this.progressFrom = progressFrom;
2265
- this.progressValue = progressValue;
2266
- this.mMax = mMax;
2267
- if (progressFrom < 0) {
2268
- throw "Progress from must be bigger than or zero";
2269
- }
2270
- if (progressValue <= 0) {
2271
- throw "Progress value must be bigger than zero";
2272
- }
2273
- this.mCurrent = 0;
2274
- }
2275
- get id() {
2276
- return this.parent.id;
2277
- }
2278
- get current() {
2279
- return this.mCurrent;
2280
- }
2281
- get max() {
2282
- return this.mMax;
2283
- }
2284
- get message() {
2285
- return this.parent.message;
2286
- }
2287
- get error() {
2288
- return this.parent.error;
2289
- }
2290
- get percent() {
2291
- return this.parent.percent;
2292
- }
2293
- get remaining() {
2294
- return this.max - this.mCurrent;
2295
- }
2296
- get canceled() {
2297
- return !this.parent || this.parent.canceled;
2298
- }
2299
- setMessageBridge(messageBridge) {
2300
- if (!this.parent)
2301
- return this;
2302
- this.parent.setMessageBridge(messageBridge);
2303
- return this;
2194
+ };
2195
+ Gallery = __decorate([
2196
+ injectable(),
2197
+ scoped(Lifecycle.ContainerScoped),
2198
+ __metadata("design:paramtypes", [Configuration, GalleryCache])
2199
+ ], Gallery);
2200
+
2201
+ let IdGenerator = class IdGenerator {
2202
+ constructor(config) {
2203
+ this.config = config;
2204
+ this.prefix = config.resolve("idPrefix");
2205
+ this.separator = config.resolve("idSeparator");
2206
+ this.chars = config.resolve("idChars");
2207
+ this.parts = config.resolve("idParts");
2304
2208
  }
2305
- createSubProgress(progressValue, max, message) {
2209
+ generate(checkCb) {
2306
2210
  return __awaiter(this, void 0, void 0, function* () {
2307
- if (max <= 0 && progressValue > 0) {
2308
- yield this.advance(progressValue);
2211
+ let id = null;
2212
+ let tries = 0;
2213
+ let notGood = true;
2214
+ while (notGood && tries < 5) {
2215
+ id = this.generateId();
2216
+ notGood = yield checkCb(id);
2217
+ tries++;
2309
2218
  }
2310
- if (message !== null) {
2311
- yield this.setMessage(message);
2219
+ if (notGood) {
2220
+ throw `Couldn't generate an unique id..`;
2312
2221
  }
2313
- return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
2222
+ return id;
2314
2223
  });
2315
2224
  }
2316
- setMax(max) {
2317
- return __awaiter(this, void 0, void 0, function* () {
2318
- if (isNaN(max) || max <= 0) {
2319
- throw "Max progress value must be bigger than zero";
2225
+ generateId() {
2226
+ return this.prefix + this.parts.map(num => {
2227
+ let s = "";
2228
+ for (let i = 0; i < num; i++) {
2229
+ const ix = rand(0, this.chars.length - 1);
2230
+ s += this.chars[ix];
2320
2231
  }
2321
- this.mMax = max;
2322
- yield this.save();
2323
- });
2324
- }
2325
- setMessage(message) {
2326
- return __awaiter(this, void 0, void 0, function* () {
2327
- if (!this.parent)
2328
- return null;
2329
- yield this.parent.setMessage(message);
2330
- });
2232
+ return s;
2233
+ }).join(this.separator);
2331
2234
  }
2332
- setError(error) {
2333
- return __awaiter(this, void 0, void 0, function* () {
2334
- if (!this.parent)
2335
- return null;
2336
- yield this.parent.setError(error);
2337
- });
2235
+ };
2236
+ IdGenerator = __decorate([
2237
+ injectable(),
2238
+ scoped(Lifecycle.ContainerScoped),
2239
+ __metadata("design:paramtypes", [Configuration])
2240
+ ], IdGenerator);
2241
+
2242
+ let TranslationProvider = class TranslationProvider {
2243
+ constructor(config, cache) {
2244
+ this.config = config;
2245
+ this.cache = cache;
2338
2246
  }
2339
- advance(value = 1) {
2340
- return __awaiter(this, void 0, void 0, function* () {
2341
- if (isNaN(value) || value <= 0) {
2342
- throw "Advance value must be bigger than zero";
2247
+ getDictionary(language) {
2248
+ return this.cache.getOrSet(`translations-${language}`, () => __awaiter(this, void 0, void 0, function* () {
2249
+ try {
2250
+ const url = this.config.resolve("translationsTemplate")
2251
+ .replace(`__lang__`, language)
2252
+ .replace(`[lang]`, language);
2253
+ const data = yield axios.get(url).then(t => t.data);
2254
+ if (isObject(data[language])) {
2255
+ return data[language];
2256
+ }
2257
+ return data;
2343
2258
  }
2344
- this.mCurrent = Math.min(this.max, this.mCurrent + value);
2345
- yield this.save();
2346
- });
2347
- }
2348
- cancel() {
2349
- return __awaiter(this, void 0, void 0, function* () {
2350
- if (!this.parent)
2351
- return null;
2352
- yield this.parent.cancel();
2353
- });
2354
- }
2355
- save() {
2356
- return __awaiter(this, void 0, void 0, function* () {
2357
- const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
2358
- const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
2359
- const current = this.parent.current;
2360
- if (newProgress <= current)
2361
- return null;
2362
- yield this.parent.advance(newProgress);
2363
- });
2364
- }
2365
- load() {
2366
- return __awaiter(this, void 0, void 0, function* () {
2367
- return null;
2368
- });
2369
- }
2370
- toJSON() {
2371
- return this.parent.toJSON();
2259
+ catch (e) {
2260
+ return {
2261
+ message: `${e}`
2262
+ };
2263
+ }
2264
+ }), 5 * 60);
2372
2265
  }
2373
- }
2266
+ };
2267
+ TranslationProvider = __decorate([
2268
+ singleton(),
2269
+ __metadata("design:paramtypes", [Configuration, Cache])
2270
+ ], TranslationProvider);
2374
2271
 
2375
- let Progresses = class Progresses {
2376
- constructor(connector, jobMan) {
2377
- this.connector = connector;
2378
- this.jobMan = jobMan;
2379
- this.collection = connector.database.collection("progresses");
2380
- this.progresses = {};
2381
- this.jobMan.on("progress-changed", progress => {
2382
- const id = progress.id;
2383
- this.progresses[id] = new Progress(new ObjectId$1(id), progress, this.collection);
2384
- });
2272
+ let Translator = class Translator {
2273
+ constructor(translationProvider) {
2274
+ this.translationProvider = translationProvider;
2275
+ this.dictionaries = {};
2385
2276
  }
2386
- waitToFinish(id) {
2277
+ getDictionary(language) {
2387
2278
  return __awaiter(this, void 0, void 0, function* () {
2388
- return Promise.race([
2389
- this.waitForProgress(id, () => __awaiter(this, void 0, void 0, function* () {
2390
- let progress = this.progresses[id];
2391
- if (!progress || progress.percent < 100) {
2392
- progress = yield this.get(id);
2393
- }
2394
- if (!progress) {
2395
- throw new Error(`Progress does not exists with id: ${id}`);
2396
- }
2397
- return progress;
2398
- }), 500),
2399
- this.waitForProgress(id, () => __awaiter(this, void 0, void 0, function* () {
2400
- return this.progresses[id] || null;
2401
- }), 25)
2402
- ]);
2279
+ this.dictionaries[language] = yield this.translationProvider.getDictionary(language);
2280
+ return this.dictionaries[language];
2403
2281
  });
2404
2282
  }
2405
- get(id) {
2406
- return __awaiter(this, void 0, void 0, function* () {
2407
- return !id ? null : this.find({ _id: new ObjectId$1(id) });
2408
- });
2283
+ getTranslationSync(language, key, params) {
2284
+ if (!isString(key) || !key.length) {
2285
+ throw new Error(`Parameter "key" required`);
2286
+ }
2287
+ const dictionary = this.dictionaries[language];
2288
+ const translation = getValue(dictionary, key, key) || key;
2289
+ return this.interpolate(translation, params);
2409
2290
  }
2410
- find(where) {
2411
- return __awaiter(this, void 0, void 0, function* () {
2412
- const data = yield this.collection.findOne(where);
2413
- return !data ? null : new Progress(data._id, data, this.collection);
2291
+ getTranslation(language, key, params) {
2292
+ if (!isString(key) || !key.length) {
2293
+ throw new Error(`Parameter "key" required`);
2294
+ }
2295
+ return this.getDictionary(language).then(dictionary => {
2296
+ const translation = getValue(dictionary, key, key) || key;
2297
+ return this.interpolate(translation, params);
2414
2298
  });
2415
2299
  }
2416
- create(max = 100) {
2417
- return __awaiter(this, void 0, void 0, function* () {
2418
- if (isNaN(max) || max <= 0) {
2419
- throw new Error(`Max progress value must be bigger than zero`);
2420
- }
2421
- const data = {
2422
- current: 0,
2423
- max: max,
2424
- message: "",
2425
- error: "",
2426
- canceled: false
2427
- };
2428
- const res = yield this.collection.insertOne(data);
2429
- return new Progress(res.insertedId, data, this.collection);
2300
+ getTranslations(language, ...keys) {
2301
+ return new Promise(resolve => {
2302
+ Promise.all(keys.map(key => this.getTranslation(language, key))).then(translations => {
2303
+ resolve(keys.reduce((result, key, i) => {
2304
+ result[key] = translations[i];
2305
+ return result;
2306
+ }, {}));
2307
+ });
2430
2308
  });
2431
2309
  }
2432
- remove(id) {
2433
- return __awaiter(this, void 0, void 0, function* () {
2434
- yield this.collection.deleteOne({ _id: new ObjectId$1(id) });
2435
- return id;
2436
- });
2310
+ interpolate(expr, params) {
2311
+ if (typeof expr === "string") {
2312
+ return this.interpolateString(expr, params);
2313
+ }
2314
+ if (typeof expr === "function") {
2315
+ return expr(params);
2316
+ }
2317
+ return expr;
2437
2318
  }
2438
- waitForProgress(id, cb, delay) {
2439
- return __awaiter(this, void 0, void 0, function* () {
2440
- let isFinished = false;
2441
- let progress = null;
2442
- let waitTime = 0;
2443
- while (!isFinished) {
2444
- progress = yield cb();
2445
- waitTime += delay;
2446
- if (progress) {
2447
- if (progress.error) {
2448
- throw new Error(progress.error);
2449
- }
2450
- isFinished = progress.percent >= 100;
2451
- }
2452
- if (!isFinished) {
2453
- if (waitTime >= this.jobMan.maxTimeout) {
2454
- throw new Error(`Progress with id: ${id} probably never will be finished!`);
2455
- }
2456
- yield promiseTimeout(delay);
2457
- }
2458
- }
2459
- return progress;
2319
+ interpolateString(expr, params) {
2320
+ if (!expr || !params)
2321
+ return expr;
2322
+ return expr.replace(/{{\s?([^{}\s]*)\s?}}/g, (substring, b) => {
2323
+ const r = getValue(params, b);
2324
+ return isDefined(r) ? r : substring;
2460
2325
  });
2461
2326
  }
2462
2327
  };
2463
- Progresses = __decorate([
2464
- singleton()
2465
- ], Progresses);
2328
+ Translator = __decorate([
2329
+ injectable(),
2330
+ singleton(),
2331
+ __metadata("design:paramtypes", [TranslationProvider])
2332
+ ], Translator);
2466
2333
 
2467
2334
  let TemplateRenderer = class TemplateRenderer {
2468
2335
  constructor(translator, config) {
@@ -2504,27 +2371,275 @@ let TemplateRenderer = class TemplateRenderer {
2504
2371
  this.templates[fullName] = Handlebars.compile(content);
2505
2372
  Handlebars.registerPartial(fullName, content);
2506
2373
  }
2507
- resolve();
2508
- }));
2509
- });
2374
+ resolve();
2375
+ }));
2376
+ });
2377
+ });
2378
+ }
2379
+ render(template, language, context) {
2380
+ return __awaiter(this, void 0, void 0, function* () {
2381
+ yield this.init();
2382
+ yield this.translator.getDictionary(language);
2383
+ if (!this.templates[template]) {
2384
+ return Promise.reject(`Template not found with name: ${template}`);
2385
+ }
2386
+ context = Object.assign({ language }, context || {});
2387
+ const res = this.templates[template](context);
2388
+ return res instanceof Error ? yield Promise.reject(res) : res;
2389
+ });
2390
+ }
2391
+ };
2392
+ TemplateRenderer = __decorate([
2393
+ singleton(),
2394
+ __metadata("design:paramtypes", [Translator, Configuration])
2395
+ ], TemplateRenderer);
2396
+
2397
+ let MailSender = class MailSender {
2398
+ constructor(config, renderer) {
2399
+ this.config = config;
2400
+ this.renderer = renderer;
2401
+ this.transporter = createTransport({
2402
+ host: this.config.resolve("smtpHost"),
2403
+ port: this.config.resolve("smtpPort"),
2404
+ auth: {
2405
+ user: this.config.resolve("smtpUser"),
2406
+ pass: this.config.resolve("smtpPassword"),
2407
+ }
2408
+ });
2409
+ }
2410
+ get translator() {
2411
+ return this.renderer.translator;
2412
+ }
2413
+ sendMail(language, options) {
2414
+ return __awaiter(this, void 0, void 0, function* () {
2415
+ const subject = yield this.translator.getTranslation(language, options.subject || "-");
2416
+ const html = yield this.renderer.render(options.template, language, options.context);
2417
+ return this.transporter.sendMail({
2418
+ from: options.from || this.config.resolve("mailSenderAddress"),
2419
+ to: options.to,
2420
+ attachments: options.attachments,
2421
+ subject,
2422
+ html
2423
+ });
2424
+ });
2425
+ }
2426
+ };
2427
+ MailSender = __decorate([
2428
+ singleton(),
2429
+ __metadata("design:paramtypes", [Configuration, TemplateRenderer])
2430
+ ], MailSender);
2431
+
2432
+ let MemoryCache = class MemoryCache {
2433
+ constructor(cache) {
2434
+ this.cache = cache;
2435
+ this.cacheMap = new Map();
2436
+ }
2437
+ set(key, value, ttl, expirationTimestamp = null, tags = {}) {
2438
+ return __awaiter(this, void 0, void 0, function* () {
2439
+ const now = Math.round(new Date().getTime() / 1000);
2440
+ const expTimestamp = Math.min(isNaN(ttl) ? Number.MAX_SAFE_INTEGER : ttl, 3600);
2441
+ this.cacheMap.set(key, {
2442
+ _id: key,
2443
+ data: value,
2444
+ expirationTimestamp: expTimestamp,
2445
+ expiresAt: now + expTimestamp,
2446
+ });
2447
+ return this.cache.set(key, value, ttl, expirationTimestamp, tags);
2448
+ });
2449
+ }
2450
+ get(key) {
2451
+ return __awaiter(this, void 0, void 0, function* () {
2452
+ let item = this.cacheMap.get(key);
2453
+ const now = Math.round(new Date().getTime() / 1000);
2454
+ let expTimestamp = 3600;
2455
+ if (item && item.expiresAt && item.expiresAt < now) {
2456
+ expTimestamp = item.expirationTimestamp;
2457
+ item = null;
2458
+ }
2459
+ if (!item) {
2460
+ const value = yield this.cache.get(key);
2461
+ this.cacheMap.set(key, {
2462
+ _id: key,
2463
+ data: value,
2464
+ expirationTimestamp: expTimestamp,
2465
+ expiresAt: now + expTimestamp,
2466
+ });
2467
+ return value;
2468
+ }
2469
+ return item.data;
2470
+ });
2471
+ }
2472
+ getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
2473
+ return __awaiter(this, void 0, void 0, function* () {
2474
+ try {
2475
+ return yield this.get(key);
2476
+ }
2477
+ catch (e) {
2478
+ return yield this.set(key, yield valueCb(), ttl, expirationTimestamp, tags);
2479
+ }
2480
+ });
2481
+ }
2482
+ delete(key) {
2483
+ return __awaiter(this, void 0, void 0, function* () {
2484
+ this.cacheMap.delete(key);
2485
+ yield this.cacheMap.delete(key);
2486
+ });
2487
+ }
2488
+ };
2489
+ MemoryCache = __decorate([
2490
+ injectable(),
2491
+ scoped(Lifecycle.ContainerScoped),
2492
+ __metadata("design:paramtypes", [Cache])
2493
+ ], MemoryCache);
2494
+
2495
+ function checkValue(multi, value) {
2496
+ if (multi) {
2497
+ return Array.isArray(value) && value.every(v => {
2498
+ try {
2499
+ const id = new ObjectId$1(v);
2500
+ return id instanceof ObjectId$1;
2501
+ }
2502
+ catch (e) {
2503
+ return false;
2504
+ }
2505
+ });
2506
+ }
2507
+ if (null === value)
2508
+ return true;
2509
+ try {
2510
+ const id = new ObjectId$1(value);
2511
+ return id instanceof ObjectId$1;
2512
+ }
2513
+ catch (e) {
2514
+ return false;
2515
+ }
2516
+ }
2517
+ let IsFile = class IsFile {
2518
+ validate(value, validationArguments) {
2519
+ const [multi] = (validationArguments.constraints || []);
2520
+ return checkValue(multi, value);
2521
+ }
2522
+ };
2523
+ IsFile = __decorate([
2524
+ ValidatorConstraint()
2525
+ ], IsFile);
2526
+ let IsObjectId = class IsObjectId {
2527
+ validate(value, validationArguments) {
2528
+ const [_, multi] = (validationArguments.constraints || []);
2529
+ return checkValue(multi, value);
2530
+ }
2531
+ };
2532
+ IsObjectId = __decorate([
2533
+ ValidatorConstraint()
2534
+ ], IsObjectId);
2535
+
2536
+ let OpenApi = class OpenApi {
2537
+ constructor(container, customValidation) {
2538
+ this.container = container;
2539
+ this.customValidation = customValidation;
2540
+ this.docs = null;
2541
+ }
2542
+ get apiDocs() {
2543
+ if (!this.docs)
2544
+ this.docs = this.createApiDocs();
2545
+ return this.docs;
2546
+ }
2547
+ get apiDocsStr() {
2548
+ if (!this.docsStr)
2549
+ this.docsStr = JSON.stringify(this.apiDocs);
2550
+ return this.docsStr;
2551
+ }
2552
+ schemaToExample(src, req) {
2553
+ var _a, _b, _c;
2554
+ return __awaiter(this, void 0, void 0, function* () {
2555
+ if (src.$ref) {
2556
+ const schemas = this.apiDocs.components.schemas;
2557
+ const schema = src.$ref
2558
+ .replace("#/components/schemas/", "")
2559
+ .replace("#/definitions/", "");
2560
+ return this.schemaToExample(schemas[schema], req);
2561
+ }
2562
+ let schema = src;
2563
+ if (schema.oneOf) {
2564
+ schema = Object.assign({}, schema, schema.oneOf[0]);
2565
+ }
2566
+ if (schema.type === "object") {
2567
+ const result = {};
2568
+ yield Promise.all(Object.keys(schema.properties).map((key) => __awaiter(this, void 0, void 0, function* () {
2569
+ result[key] = yield this.schemaToExample(schema.properties[key], req);
2570
+ })));
2571
+ return result;
2572
+ }
2573
+ if (schema.type === "array") {
2574
+ return [yield this.schemaToExample(schema.items, req)];
2575
+ }
2576
+ if (schema.type === "string") {
2577
+ if (isDefined(schema.default)) {
2578
+ if (isFunction(schema.default)) {
2579
+ return schema.default(this.container);
2580
+ }
2581
+ return schema.default;
2582
+ }
2583
+ if (schema.format == "date") {
2584
+ return new Date().toISOString().substr(0, 10);
2585
+ }
2586
+ if (schema.format == "date-time") {
2587
+ return new Date().toISOString();
2588
+ }
2589
+ if (schema.enum) {
2590
+ return schema.enum[0];
2591
+ }
2592
+ return "string";
2593
+ }
2594
+ if (schema.type === "number") {
2595
+ return (_a = schema.default) !== null && _a !== void 0 ? _a : 0;
2596
+ }
2597
+ else if (schema.type === "boolean") {
2598
+ return (_b = schema.default) !== null && _b !== void 0 ? _b : false;
2599
+ }
2600
+ else {
2601
+ return (_c = schema.default) !== null && _c !== void 0 ? _c : null;
2602
+ }
2510
2603
  });
2511
2604
  }
2512
- render(template, language, context) {
2513
- return __awaiter(this, void 0, void 0, function* () {
2514
- yield this.init();
2515
- yield this.translator.getDictionary(language);
2516
- if (!this.templates[template]) {
2517
- return Promise.reject(`Template not found with name: ${template}`);
2605
+ createApiDocs() {
2606
+ const storage = getMetadataArgsStorage();
2607
+ const docs = routingControllersToSpec(storage);
2608
+ docs.basePath = "/api/";
2609
+ docs.definitions = validationMetadatasToSchemas({
2610
+ additionalConverters: {
2611
+ [ValidationTypes.CUSTOM_VALIDATION]: (meta, options) => {
2612
+ const res = isFunction(this.customValidation) ? this.customValidation(meta, options) : this.customValidation;
2613
+ if (isObject(res))
2614
+ return res;
2615
+ const constraints = meta.constraints || [];
2616
+ if (meta.constraintCls === IsFile) {
2617
+ return {
2618
+ multi: constraints[0] || false,
2619
+ type: "file"
2620
+ };
2621
+ }
2622
+ if (meta.constraintCls === IsObjectId) {
2623
+ return {
2624
+ endpoint: constraints[0] || false,
2625
+ multi: constraints[1] || false,
2626
+ type: "list"
2627
+ };
2628
+ }
2629
+ return null;
2630
+ }
2518
2631
  }
2519
- context = Object.assign({ language }, context || {});
2520
- const res = this.templates[template](context);
2521
- return res instanceof Error ? yield Promise.reject(res) : res;
2522
2632
  });
2633
+ docs.components.schemas = docs.definitions;
2634
+ return docs;
2523
2635
  }
2524
2636
  };
2525
- TemplateRenderer = __decorate([
2526
- singleton()
2527
- ], TemplateRenderer);
2637
+ OpenApi = __decorate([
2638
+ singleton(),
2639
+ __param(0, inject(DI_CONTAINER)),
2640
+ __param(1, inject(OPENAPI_VALIDATION)),
2641
+ __metadata("design:paramtypes", [Object, Object])
2642
+ ], OpenApi);
2528
2643
 
2529
2644
  let TerminalManager = class TerminalManager {
2530
2645
  constructor(logger, config, commands) {
@@ -2587,7 +2702,9 @@ let TerminalManager = class TerminalManager {
2587
2702
  };
2588
2703
  TerminalManager = __decorate([
2589
2704
  singleton(),
2590
- __param(2, injectAll(TERMINAL_COMMAND))
2705
+ __param(2, injectAll(TERMINAL_COMMAND)),
2706
+ __metadata("design:paramtypes", [Logger,
2707
+ Configuration, Array])
2591
2708
  ], TerminalManager);
2592
2709
 
2593
2710
  let TokenGenerator = class TokenGenerator {
@@ -2620,99 +2737,10 @@ let TokenGenerator = class TokenGenerator {
2620
2737
  }
2621
2738
  };
2622
2739
  TokenGenerator = __decorate([
2623
- singleton()
2740
+ singleton(),
2741
+ __metadata("design:paramtypes", [])
2624
2742
  ], TokenGenerator);
2625
2743
 
2626
- let TranslationProvider = class TranslationProvider {
2627
- constructor(config, cache) {
2628
- this.config = config;
2629
- this.cache = cache;
2630
- }
2631
- getDictionary(language) {
2632
- return this.cache.getOrSet(`translations-${language}`, () => __awaiter(this, void 0, void 0, function* () {
2633
- try {
2634
- const url = this.config.resolve("translationsTemplate")
2635
- .replace(`__lang__`, language)
2636
- .replace(`[lang]`, language);
2637
- const data = yield axios.get(url).then(t => t.data);
2638
- if (isObject(data[language])) {
2639
- return data[language];
2640
- }
2641
- return data;
2642
- }
2643
- catch (e) {
2644
- return {
2645
- message: `${e}`
2646
- };
2647
- }
2648
- }), 5 * 60);
2649
- }
2650
- };
2651
- TranslationProvider = __decorate([
2652
- singleton()
2653
- ], TranslationProvider);
2654
-
2655
- let Translator = class Translator {
2656
- constructor(translationProvider) {
2657
- this.translationProvider = translationProvider;
2658
- this.dictionaries = {};
2659
- }
2660
- getDictionary(language) {
2661
- return __awaiter(this, void 0, void 0, function* () {
2662
- this.dictionaries[language] = yield this.translationProvider.getDictionary(language);
2663
- return this.dictionaries[language];
2664
- });
2665
- }
2666
- getTranslationSync(language, key, params) {
2667
- if (!isString(key) || !key.length) {
2668
- throw new Error(`Parameter "key" required`);
2669
- }
2670
- const dictionary = this.dictionaries[language];
2671
- const translation = getValue(dictionary, key, key) || key;
2672
- return this.interpolate(translation, params);
2673
- }
2674
- getTranslation(language, key, params) {
2675
- if (!isString(key) || !key.length) {
2676
- throw new Error(`Parameter "key" required`);
2677
- }
2678
- return this.getDictionary(language).then(dictionary => {
2679
- const translation = getValue(dictionary, key, key) || key;
2680
- return this.interpolate(translation, params);
2681
- });
2682
- }
2683
- getTranslations(language, ...keys) {
2684
- return new Promise(resolve => {
2685
- Promise.all(keys.map(key => this.getTranslation(language, key))).then(translations => {
2686
- resolve(keys.reduce((result, key, i) => {
2687
- result[key] = translations[i];
2688
- return result;
2689
- }, {}));
2690
- });
2691
- });
2692
- }
2693
- interpolate(expr, params) {
2694
- if (typeof expr === "string") {
2695
- return this.interpolateString(expr, params);
2696
- }
2697
- if (typeof expr === "function") {
2698
- return expr(params);
2699
- }
2700
- return expr;
2701
- }
2702
- interpolateString(expr, params) {
2703
- if (!expr || !params)
2704
- return expr;
2705
- return expr.replace(/{{\s?([^{}\s]*)\s?}}/g, (substring, b) => {
2706
- const r = getValue(params, b);
2707
- return isDefined(r) ? r : substring;
2708
- });
2709
- }
2710
- };
2711
- Translator = __decorate([
2712
- injectable(),
2713
- singleton()
2714
- ], Translator);
2715
-
2716
2744
  const sampleUser = {
2717
2745
  id: "5a3cdf7c6a9cf0ba32feccdf",
2718
2746
  email: "admin@site.com",
@@ -2743,6 +2771,66 @@ UserManager = __decorate([
2743
2771
  scoped(Lifecycle.ContainerScoped)
2744
2772
  ], UserManager);
2745
2773
 
2774
+ class AssetImageParams {
2775
+ constructor() {
2776
+ this.rotation = 0;
2777
+ this.canvasScaleX = 1;
2778
+ this.canvasScaleY = 1;
2779
+ this.scaleX = 1;
2780
+ this.scaleY = 1;
2781
+ this.lazy = false;
2782
+ this.crop = false;
2783
+ this.cropBefore = false;
2784
+ this.cropAfter = false;
2785
+ }
2786
+ }
2787
+ __decorate([
2788
+ Min(-360),
2789
+ Max(360),
2790
+ IsOptional(),
2791
+ __metadata("design:type", Number)
2792
+ ], AssetImageParams.prototype, "rotation", void 0);
2793
+ __decorate([
2794
+ Min(0.0001),
2795
+ IsOptional(),
2796
+ __metadata("design:type", Number)
2797
+ ], AssetImageParams.prototype, "canvasScaleX", void 0);
2798
+ __decorate([
2799
+ Min(0.0001),
2800
+ IsOptional(),
2801
+ __metadata("design:type", Number)
2802
+ ], AssetImageParams.prototype, "canvasScaleY", void 0);
2803
+ __decorate([
2804
+ Min(0.0001),
2805
+ IsOptional(),
2806
+ __metadata("design:type", Number)
2807
+ ], AssetImageParams.prototype, "scaleX", void 0);
2808
+ __decorate([
2809
+ Min(0.0001),
2810
+ IsOptional(),
2811
+ __metadata("design:type", Number)
2812
+ ], AssetImageParams.prototype, "scaleY", void 0);
2813
+ __decorate([
2814
+ IsBoolean(),
2815
+ IsOptional(),
2816
+ __metadata("design:type", Boolean)
2817
+ ], AssetImageParams.prototype, "lazy", void 0);
2818
+ __decorate([
2819
+ IsBoolean(),
2820
+ IsOptional(),
2821
+ __metadata("design:type", Boolean)
2822
+ ], AssetImageParams.prototype, "crop", void 0);
2823
+ __decorate([
2824
+ IsBoolean(),
2825
+ IsOptional(),
2826
+ __metadata("design:type", Boolean)
2827
+ ], AssetImageParams.prototype, "cropBefore", void 0);
2828
+ __decorate([
2829
+ IsBoolean(),
2830
+ IsOptional(),
2831
+ __metadata("design:type", Boolean)
2832
+ ], AssetImageParams.prototype, "cropAfter", void 0);
2833
+
2746
2834
  let AssetsController = class AssetsController {
2747
2835
  constructor(assets, assetResolver) {
2748
2836
  this.assets = assets;
@@ -2842,46 +2930,68 @@ let AssetsController = class AssetsController {
2842
2930
  __decorate([
2843
2931
  Authorized(),
2844
2932
  Post(""),
2845
- __param(0, UploadedFile("file"))
2933
+ __param(0, UploadedFile("file")),
2934
+ __metadata("design:type", Function),
2935
+ __metadata("design:paramtypes", [Object]),
2936
+ __metadata("design:returntype", Promise)
2846
2937
  ], AssetsController.prototype, "upload", null);
2847
2938
  __decorate([
2848
2939
  Authorized(),
2849
2940
  Post("url"),
2850
- __param(0, Body())
2941
+ __param(0, Body()),
2942
+ __metadata("design:type", Function),
2943
+ __metadata("design:paramtypes", [Object]),
2944
+ __metadata("design:returntype", Promise)
2851
2945
  ], AssetsController.prototype, "uploadUrl", null);
2852
2946
  __decorate([
2853
2947
  Get("/:id"),
2854
2948
  __param(0, Param("id")),
2855
2949
  __param(1, QueryParam("lazy")),
2856
- __param(2, Res())
2950
+ __param(2, Res()),
2951
+ __metadata("design:type", Function),
2952
+ __metadata("design:paramtypes", [String, Boolean, Object]),
2953
+ __metadata("design:returntype", Promise)
2857
2954
  ], AssetsController.prototype, "getFile", null);
2858
2955
  __decorate([
2859
2956
  Get("/image/:id/:rotation"),
2860
2957
  __param(0, Param("id")),
2861
2958
  __param(1, QueryParams()),
2862
2959
  __param(2, Res()),
2863
- __param(3, Param("rotation"))
2960
+ __param(3, Param("rotation")),
2961
+ __metadata("design:type", Function),
2962
+ __metadata("design:paramtypes", [String, AssetImageParams, Object, Number]),
2963
+ __metadata("design:returntype", Promise)
2864
2964
  ], AssetsController.prototype, "getImageRotation", null);
2865
2965
  __decorate([
2866
2966
  Get("/image/:id"),
2867
2967
  __param(0, Param("id")),
2868
2968
  __param(1, QueryParams()),
2869
- __param(2, Res())
2969
+ __param(2, Res()),
2970
+ __metadata("design:type", Function),
2971
+ __metadata("design:paramtypes", [String, AssetImageParams, Object]),
2972
+ __metadata("design:returntype", Promise)
2870
2973
  ], AssetsController.prototype, "getImage", null);
2871
2974
  __decorate([
2872
2975
  Get("/by-name/:name"),
2873
2976
  __param(0, Param("name")),
2874
- __param(1, Res())
2977
+ __param(1, Res()),
2978
+ __metadata("design:type", Function),
2979
+ __metadata("design:paramtypes", [String, Object]),
2980
+ __metadata("design:returntype", Promise)
2875
2981
  ], AssetsController.prototype, "getFileByName", null);
2876
2982
  __decorate([
2877
2983
  Get("/by-name/image/:name"),
2878
2984
  __param(0, Param("name")),
2879
2985
  __param(1, QueryParams()),
2880
- __param(2, Res())
2986
+ __param(2, Res()),
2987
+ __metadata("design:type", Function),
2988
+ __metadata("design:paramtypes", [String, AssetImageParams, Object]),
2989
+ __metadata("design:returntype", Promise)
2881
2990
  ], AssetsController.prototype, "getImageByName", null);
2882
2991
  AssetsController = __decorate([
2883
2992
  injectable(),
2884
- Controller("/assets")
2993
+ Controller("/assets"),
2994
+ __metadata("design:paramtypes", [Assets, AssetResolver])
2885
2995
  ], AssetsController);
2886
2996
 
2887
2997
  let AuthController = class AuthController {
@@ -2914,16 +3024,23 @@ let AuthController = class AuthController {
2914
3024
  __decorate([
2915
3025
  Post("/login"),
2916
3026
  __param(0, Body()),
2917
- __param(1, Res())
3027
+ __param(1, Res()),
3028
+ __metadata("design:type", Function),
3029
+ __metadata("design:paramtypes", [Object, Object]),
3030
+ __metadata("design:returntype", Promise)
2918
3031
  ], AuthController.prototype, "login", null);
2919
3032
  __decorate([
2920
3033
  Authorized(),
2921
3034
  Get("/user"),
2922
- __param(0, CurrentUser())
3035
+ __param(0, CurrentUser()),
3036
+ __metadata("design:type", Function),
3037
+ __metadata("design:paramtypes", [Object]),
3038
+ __metadata("design:returntype", void 0)
2923
3039
  ], AuthController.prototype, "getProfile", null);
2924
3040
  AuthController = __decorate([
2925
3041
  injectable(),
2926
- Controller()
3042
+ Controller(),
3043
+ __metadata("design:paramtypes", [Configuration, UserManager])
2927
3044
  ], AuthController);
2928
3045
 
2929
3046
  let GalleryController = class GalleryController {
@@ -2936,11 +3053,15 @@ let GalleryController = class GalleryController {
2936
3053
  };
2937
3054
  __decorate([
2938
3055
  Get("/:id"),
2939
- __param(0, Param("id"))
3056
+ __param(0, Param("id")),
3057
+ __metadata("design:type", Function),
3058
+ __metadata("design:paramtypes", [String]),
3059
+ __metadata("design:returntype", void 0)
2940
3060
  ], GalleryController.prototype, "getFile", null);
2941
3061
  GalleryController = __decorate([
2942
3062
  injectable(),
2943
- Controller("/gallery")
3063
+ Controller("/gallery"),
3064
+ __metadata("design:paramtypes", [GalleryCache])
2944
3065
  ], GalleryController);
2945
3066
 
2946
3067
  let ProgressesController = class ProgressesController {
@@ -2963,11 +3084,15 @@ let ProgressesController = class ProgressesController {
2963
3084
  };
2964
3085
  __decorate([
2965
3086
  Get("/:id"),
2966
- __param(0, Param("id"))
3087
+ __param(0, Param("id")),
3088
+ __metadata("design:type", Function),
3089
+ __metadata("design:paramtypes", [String]),
3090
+ __metadata("design:returntype", Promise)
2967
3091
  ], ProgressesController.prototype, "getProgress", null);
2968
3092
  ProgressesController = __decorate([
2969
3093
  injectable(),
2970
- Controller("/progresses")
3094
+ Controller("/progresses"),
3095
+ __metadata("design:paramtypes", [Progresses, Configuration])
2971
3096
  ], ProgressesController);
2972
3097
 
2973
3098
  // Add a comment hint for webstorm to style the string as css
@@ -3142,19 +3267,29 @@ let TerminalController$1 = class TerminalController {
3142
3267
  };
3143
3268
  __decorate([
3144
3269
  Get("/terminal"),
3145
- Header("Content-Type", "text/html")
3270
+ Header("Content-Type", "text/html"),
3271
+ __metadata("design:type", Function),
3272
+ __metadata("design:paramtypes", []),
3273
+ __metadata("design:returntype", void 0)
3146
3274
  ], TerminalController$1.prototype, "terminal", null);
3147
3275
  __decorate([
3148
3276
  Get("/console"),
3149
- Header("Content-Type", "text/html")
3277
+ Header("Content-Type", "text/html"),
3278
+ __metadata("design:type", Function),
3279
+ __metadata("design:paramtypes", []),
3280
+ __metadata("design:returntype", void 0)
3150
3281
  ], TerminalController$1.prototype, "console", null);
3151
3282
  __decorate([
3152
3283
  Get(),
3153
- Header("Content-Type", "text/html")
3284
+ Header("Content-Type", "text/html"),
3285
+ __metadata("design:type", Function),
3286
+ __metadata("design:paramtypes", [String]),
3287
+ __metadata("design:returntype", String)
3154
3288
  ], TerminalController$1.prototype, "generateClient", null);
3155
3289
  TerminalController$1 = __decorate([
3156
3290
  injectable(),
3157
- Controller()
3291
+ Controller(),
3292
+ __metadata("design:paramtypes", [Configuration])
3158
3293
  ], TerminalController$1);
3159
3294
 
3160
3295
  let ErrorHandlerMiddleware = class ErrorHandlerMiddleware {
@@ -3228,7 +3363,8 @@ let ErrorHandlerMiddleware = class ErrorHandlerMiddleware {
3228
3363
  };
3229
3364
  ErrorHandlerMiddleware = __decorate([
3230
3365
  injectable(),
3231
- Middleware({ type: "after" })
3366
+ Middleware({ type: "after" }),
3367
+ __metadata("design:paramtypes", [Configuration, Translator])
3232
3368
  ], ErrorHandlerMiddleware);
3233
3369
 
3234
3370
  let ContainerMiddleware = class ContainerMiddleware {
@@ -3243,7 +3379,8 @@ let ContainerMiddleware = class ContainerMiddleware {
3243
3379
  ContainerMiddleware = __decorate([
3244
3380
  injectable(),
3245
3381
  Middleware({ type: "before" }),
3246
- __param(0, inject(DI_CONTAINER))
3382
+ __param(0, inject(DI_CONTAINER)),
3383
+ __metadata("design:paramtypes", [Object])
3247
3384
  ], ContainerMiddleware);
3248
3385
 
3249
3386
  let LanguageMiddleware = class LanguageMiddleware {
@@ -3257,7 +3394,8 @@ let LanguageMiddleware = class LanguageMiddleware {
3257
3394
  };
3258
3395
  LanguageMiddleware = __decorate([
3259
3396
  injectable(),
3260
- Middleware({ type: "before" })
3397
+ Middleware({ type: "before" }),
3398
+ __metadata("design:paramtypes", [Configuration])
3261
3399
  ], LanguageMiddleware);
3262
3400
 
3263
3401
  let RequestEndedMiddleware = class RequestEndedMiddleware {
@@ -3275,7 +3413,8 @@ let RequestEndedMiddleware = class RequestEndedMiddleware {
3275
3413
  };
3276
3414
  RequestEndedMiddleware = __decorate([
3277
3415
  injectable(),
3278
- Middleware({ type: "after" })
3416
+ Middleware({ type: "after" }),
3417
+ __metadata("design:paramtypes", [Logger])
3279
3418
  ], RequestEndedMiddleware);
3280
3419
 
3281
3420
  let RequestStartedMiddleware = class RequestStartedMiddleware {
@@ -3291,7 +3430,8 @@ let RequestStartedMiddleware = class RequestStartedMiddleware {
3291
3430
  };
3292
3431
  RequestStartedMiddleware = __decorate([
3293
3432
  injectable(),
3294
- Middleware({ type: "before" })
3433
+ Middleware({ type: "before" }),
3434
+ __metadata("design:paramtypes", [Logger])
3295
3435
  ], RequestStartedMiddleware);
3296
3436
 
3297
3437
  let ProgressController = class ProgressController {
@@ -3331,17 +3471,24 @@ let ProgressController = class ProgressController {
3331
3471
  __decorate([
3332
3472
  OnMessage("background-progress"),
3333
3473
  __param(0, ConnectedSocket()),
3334
- __param(1, MessageBody())
3474
+ __param(1, MessageBody()),
3475
+ __metadata("design:type", Function),
3476
+ __metadata("design:paramtypes", [Object, String]),
3477
+ __metadata("design:returntype", Promise)
3335
3478
  ], ProgressController.prototype, "advanceProgress", null);
3336
3479
  __decorate([
3337
3480
  OnMessage("background-progress-interest"),
3338
3481
  __param(0, ConnectedSocket()),
3339
- __param(1, MessageBody())
3482
+ __param(1, MessageBody()),
3483
+ __metadata("design:type", Function),
3484
+ __metadata("design:paramtypes", [Object, String]),
3485
+ __metadata("design:returntype", Promise)
3340
3486
  ], ProgressController.prototype, "setProgressInterest", null);
3341
3487
  ProgressController = __decorate([
3342
3488
  singleton(),
3343
3489
  SocketController(),
3344
- __param(1, inject(SOCKET_SERVER))
3490
+ __param(1, inject(SOCKET_SERVER)),
3491
+ __metadata("design:paramtypes", [Progresses, Server])
3345
3492
  ], ProgressController);
3346
3493
 
3347
3494
  class Terminal {
@@ -3462,21 +3609,31 @@ let TerminalController = class TerminalController {
3462
3609
  };
3463
3610
  __decorate([
3464
3611
  OnMessage("terminal-init"),
3465
- __param(0, ConnectedSocket())
3612
+ __param(0, ConnectedSocket()),
3613
+ __metadata("design:type", Function),
3614
+ __metadata("design:paramtypes", [Object]),
3615
+ __metadata("design:returntype", Promise)
3466
3616
  ], TerminalController.prototype, "terminalInit", null);
3467
3617
  __decorate([
3468
3618
  OnMessage("terminal-data"),
3469
3619
  __param(0, ConnectedSocket()),
3470
- __param(1, MessageBody())
3620
+ __param(1, MessageBody()),
3621
+ __metadata("design:type", Function),
3622
+ __metadata("design:paramtypes", [Object, String]),
3623
+ __metadata("design:returntype", Promise)
3471
3624
  ], TerminalController.prototype, "terminalData", null);
3472
3625
  __decorate([
3473
3626
  OnMessage("terminal-upload"),
3474
3627
  __param(0, ConnectedSocket()),
3475
- __param(1, MessageBody())
3628
+ __param(1, MessageBody()),
3629
+ __metadata("design:type", Function),
3630
+ __metadata("design:paramtypes", [Object, Object]),
3631
+ __metadata("design:returntype", Promise)
3476
3632
  ], TerminalController.prototype, "terminalUpload", null);
3477
3633
  TerminalController = __decorate([
3478
3634
  singleton(),
3479
- SocketController()
3635
+ SocketController(),
3636
+ __metadata("design:paramtypes", [TerminalManager])
3480
3637
  ], TerminalController);
3481
3638
 
3482
3639
  let CompressionMiddleware = class CompressionMiddleware {
@@ -3748,7 +3905,8 @@ let FixturesCommand = class FixturesCommand {
3748
3905
  };
3749
3906
  FixturesCommand = __decorate([
3750
3907
  injectable(),
3751
- scoped(Lifecycle.ContainerScoped)
3908
+ scoped(Lifecycle.ContainerScoped),
3909
+ __metadata("design:paramtypes", [Fixtures])
3752
3910
  ], FixturesCommand);
3753
3911
 
3754
3912
  const commands = [
@@ -3756,57 +3914,6 @@ const commands = [
3756
3914
  FixturesCommand
3757
3915
  ];
3758
3916
 
3759
- class AssetImageParams {
3760
- constructor() {
3761
- this.rotation = 0;
3762
- this.canvasScaleX = 1;
3763
- this.canvasScaleY = 1;
3764
- this.scaleX = 1;
3765
- this.scaleY = 1;
3766
- this.lazy = false;
3767
- this.crop = false;
3768
- this.cropBefore = false;
3769
- this.cropAfter = false;
3770
- }
3771
- }
3772
- __decorate([
3773
- Min(-360),
3774
- Max(360),
3775
- IsOptional()
3776
- ], AssetImageParams.prototype, "rotation", void 0);
3777
- __decorate([
3778
- Min(0.0001),
3779
- IsOptional()
3780
- ], AssetImageParams.prototype, "canvasScaleX", void 0);
3781
- __decorate([
3782
- Min(0.0001),
3783
- IsOptional()
3784
- ], AssetImageParams.prototype, "canvasScaleY", void 0);
3785
- __decorate([
3786
- Min(0.0001),
3787
- IsOptional()
3788
- ], AssetImageParams.prototype, "scaleX", void 0);
3789
- __decorate([
3790
- Min(0.0001),
3791
- IsOptional()
3792
- ], AssetImageParams.prototype, "scaleY", void 0);
3793
- __decorate([
3794
- IsBoolean(),
3795
- IsOptional()
3796
- ], AssetImageParams.prototype, "lazy", void 0);
3797
- __decorate([
3798
- IsBoolean(),
3799
- IsOptional()
3800
- ], AssetImageParams.prototype, "crop", void 0);
3801
- __decorate([
3802
- IsBoolean(),
3803
- IsOptional()
3804
- ], AssetImageParams.prototype, "cropBefore", void 0);
3805
- __decorate([
3806
- IsBoolean(),
3807
- IsOptional()
3808
- ], AssetImageParams.prototype, "cropAfter", void 0);
3809
-
3810
3917
  class BaseDoc {
3811
3918
  /**
3812
3919
  * Casts this to DocumentType<this> to allow using document methods in get/set-s