@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.
- package/esm2020/commands/fixtures-command.mjs +5 -3
- package/esm2020/requests/asset-image-params.mjs +20 -11
- package/esm2020/rest-controllers/assets.controller.mjs +35 -10
- package/esm2020/rest-controllers/auth.controller.mjs +14 -5
- package/esm2020/rest-controllers/gallery.controller.mjs +9 -4
- package/esm2020/rest-controllers/progresses.controller.mjs +10 -4
- package/esm2020/rest-controllers/terminal.controller.mjs +17 -6
- package/esm2020/rest-middlewares/container.middleware.mjs +4 -3
- package/esm2020/rest-middlewares/error-handler.middleware.mjs +6 -3
- package/esm2020/rest-middlewares/language.middleware.mjs +5 -3
- package/esm2020/rest-middlewares/request-ended.middleware.mjs +5 -3
- package/esm2020/rest-middlewares/request-started.middleware.mjs +5 -3
- package/esm2020/services/asset-resolver.mjs +6 -3
- package/esm2020/services/assets.mjs +6 -3
- package/esm2020/services/backend-provider.mjs +4 -3
- package/esm2020/services/cache.mjs +7 -3
- package/esm2020/services/configuration.mjs +4 -3
- package/esm2020/services/fixtures.mjs +4 -3
- package/esm2020/services/gallery-cache.mjs +4 -3
- package/esm2020/services/gallery.mjs +6 -3
- package/esm2020/services/id-generator.mjs +5 -3
- package/esm2020/services/job-manager.mjs +7 -3
- package/esm2020/services/lazy-assets.mjs +13 -3
- package/esm2020/services/logger.mjs +5 -3
- package/esm2020/services/mail-sender.mjs +6 -3
- package/esm2020/services/memory-cache.mjs +5 -3
- package/esm2020/services/mongo-connector.mjs +5 -3
- package/esm2020/services/open-api.mjs +4 -3
- package/esm2020/services/progresses.mjs +6 -3
- package/esm2020/services/template-renderer.mjs +6 -3
- package/esm2020/services/terminal-manager.mjs +7 -3
- package/esm2020/services/token-generator.mjs +4 -3
- package/esm2020/services/translation-provider.mjs +6 -3
- package/esm2020/services/translator.mjs +5 -3
- package/esm2020/socket-controllers/progress.controller.mjs +14 -5
- package/esm2020/socket-controllers/terminal.controller.mjs +17 -6
- package/fesm2015/stemy-backend.mjs +1303 -1196
- package/fesm2015/stemy-backend.mjs.map +1 -1
- package/fesm2020/stemy-backend.mjs +1369 -1262
- package/fesm2020/stemy-backend.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -4,7 +4,7 @@ import webToken from 'jsonwebtoken';
|
|
|
4
4
|
import { injectable, scoped, Lifecycle, singleton, injectAll, inject, isFactoryProvider, container } from 'tsyringe';
|
|
5
5
|
import { HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Body, Get, Param, QueryParam, Res, QueryParams, Controller, UnauthorizedError, CurrentUser, Header, BadRequestError, Middleware, createParamDecorator, useContainer, useExpressServer } from 'routing-controllers';
|
|
6
6
|
import { OnMessage, ConnectedSocket, MessageBody, SocketController, Middleware as Middleware$1, SocketControllers } from 'socket-controllers';
|
|
7
|
-
import { __decorate, __param } from 'tslib';
|
|
7
|
+
import { __decorate, __param, __metadata } from 'tslib';
|
|
8
8
|
import fontKit_ from 'fontkit';
|
|
9
9
|
import sharp_ from 'sharp';
|
|
10
10
|
import { ObjectId as ObjectId$1 } from 'bson';
|
|
@@ -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';
|
|
@@ -144,34 +144,6 @@ AssetProcessor = AssetProcessor_1 = __decorate([
|
|
|
144
144
|
scoped(Lifecycle.ContainerScoped)
|
|
145
145
|
], AssetProcessor);
|
|
146
146
|
|
|
147
|
-
let AssetResolver = class AssetResolver {
|
|
148
|
-
constructor(assets, lazyAssets) {
|
|
149
|
-
this.assets = assets;
|
|
150
|
-
this.lazyAssets = lazyAssets;
|
|
151
|
-
}
|
|
152
|
-
async resolve(id, lazy = false) {
|
|
153
|
-
let asset = null;
|
|
154
|
-
if (lazy) {
|
|
155
|
-
const lazyAsset = await this.lazyAssets.read(id);
|
|
156
|
-
if (!lazyAsset)
|
|
157
|
-
return null;
|
|
158
|
-
return lazyAsset.loadAsset();
|
|
159
|
-
}
|
|
160
|
-
asset = await this.assets.read(id);
|
|
161
|
-
if (!asset) {
|
|
162
|
-
const lazyAsset = await this.lazyAssets.read(id);
|
|
163
|
-
if (!lazyAsset)
|
|
164
|
-
return null;
|
|
165
|
-
return lazyAsset.loadAsset();
|
|
166
|
-
}
|
|
167
|
-
return asset;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
AssetResolver = __decorate([
|
|
171
|
-
injectable(),
|
|
172
|
-
scoped(Lifecycle.ContainerScoped)
|
|
173
|
-
], AssetResolver);
|
|
174
|
-
|
|
175
147
|
const sharp$2 = sharp_;
|
|
176
148
|
const diContainers = {
|
|
177
149
|
appContainer: null
|
|
@@ -851,6 +823,99 @@ async function fileTypeFromBuffer(buffer) {
|
|
|
851
823
|
return type;
|
|
852
824
|
}
|
|
853
825
|
|
|
826
|
+
let Configuration = class Configuration {
|
|
827
|
+
constructor(params) {
|
|
828
|
+
dotenv.config();
|
|
829
|
+
this.paramMap = {};
|
|
830
|
+
this.paramValues = {};
|
|
831
|
+
(params || []).forEach(param => this.add(param));
|
|
832
|
+
}
|
|
833
|
+
add(param) {
|
|
834
|
+
const existingParam = this.paramMap[param.name] || param;
|
|
835
|
+
existingParam.defaultValue = param.defaultValue;
|
|
836
|
+
existingParam.resolver = param.resolver || existingParam.resolver;
|
|
837
|
+
this.paramMap[param.name] = existingParam;
|
|
838
|
+
}
|
|
839
|
+
resolveValue(param, alreadyResolved) {
|
|
840
|
+
const envName = param.name.replace(/\.?([A-Z|0-9]+)/g, function (x, y) {
|
|
841
|
+
return "_" + y.toLowerCase();
|
|
842
|
+
}).replace(/\./gi, "_").replace(/^_/, "").toUpperCase();
|
|
843
|
+
const envValue = process.env[envName];
|
|
844
|
+
const helper = (p) => this.resolveInternal(p, alreadyResolved);
|
|
845
|
+
if (typeof envValue !== "undefined") {
|
|
846
|
+
const value = isFunction(param.resolver)
|
|
847
|
+
? param.resolver(envValue, helper)
|
|
848
|
+
: convertValue(envValue, getType(param.defaultValue));
|
|
849
|
+
console.log(colorize(`Processing param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), colorize(envName, ConsoleColor.FgBlue), `"${envValue}"`, value);
|
|
850
|
+
return value;
|
|
851
|
+
}
|
|
852
|
+
else if (isFunction(param.resolver)) {
|
|
853
|
+
const value = param.resolver(param.defaultValue, helper);
|
|
854
|
+
console.log(colorize(`Processing default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue, value);
|
|
855
|
+
return value;
|
|
856
|
+
}
|
|
857
|
+
console.log(colorize(`Using default param value`, ConsoleColor.FgYellow), colorize(param.name, ConsoleColor.FgGreen), param.defaultValue);
|
|
858
|
+
return param.defaultValue;
|
|
859
|
+
}
|
|
860
|
+
hasParam(name) {
|
|
861
|
+
return !!this.paramMap[name];
|
|
862
|
+
}
|
|
863
|
+
resolve(name) {
|
|
864
|
+
return this.resolveInternal(name, []);
|
|
865
|
+
}
|
|
866
|
+
resolveInternal(name, alreadyResolved) {
|
|
867
|
+
if (alreadyResolved.includes(name)) {
|
|
868
|
+
throw new Error(`Circular dependency detected: ${alreadyResolved.join(" -> ")} -> ${name}`);
|
|
869
|
+
}
|
|
870
|
+
alreadyResolved.push(name);
|
|
871
|
+
const param = this.paramMap[name];
|
|
872
|
+
if (!param)
|
|
873
|
+
throw new Error(`Parameter with name: '${name}' does not exists in configuration`);
|
|
874
|
+
if (!(name in this.paramValues)) {
|
|
875
|
+
this.paramValues[name] = this.resolveValue(param, alreadyResolved);
|
|
876
|
+
}
|
|
877
|
+
return this.paramValues[name];
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
Configuration = __decorate([
|
|
881
|
+
singleton(),
|
|
882
|
+
__param(0, injectAll(PARAMETER)),
|
|
883
|
+
__metadata("design:paramtypes", [Array])
|
|
884
|
+
], Configuration);
|
|
885
|
+
|
|
886
|
+
let MongoConnector = class MongoConnector {
|
|
887
|
+
constructor(configuration) {
|
|
888
|
+
this.configuration = configuration;
|
|
889
|
+
this.conn = null;
|
|
890
|
+
this.db = null;
|
|
891
|
+
this.fsBucket = null;
|
|
892
|
+
}
|
|
893
|
+
get connection() {
|
|
894
|
+
return this.conn;
|
|
895
|
+
}
|
|
896
|
+
get database() {
|
|
897
|
+
return this.db;
|
|
898
|
+
}
|
|
899
|
+
get bucket() {
|
|
900
|
+
return this.fsBucket;
|
|
901
|
+
}
|
|
902
|
+
async connect() {
|
|
903
|
+
if (this.db)
|
|
904
|
+
return this.db;
|
|
905
|
+
this.conn = (await connect(this.configuration.resolve("mongoUri"), {
|
|
906
|
+
dbName: this.configuration.resolve("mongoDb"),
|
|
907
|
+
user: this.configuration.resolve("mongoUser"),
|
|
908
|
+
pass: this.configuration.resolve("mongoPassword")
|
|
909
|
+
})).connection;
|
|
910
|
+
this.db = this.conn.db;
|
|
911
|
+
this.fsBucket = new GridFSBucket(this.db, { bucketName: "assets" });
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
MongoConnector = __decorate([
|
|
915
|
+
singleton(),
|
|
916
|
+
__metadata("design:paramtypes", [Configuration])
|
|
917
|
+
], MongoConnector);
|
|
918
|
+
|
|
854
919
|
class BaseEntity {
|
|
855
920
|
constructor(mId, data, collection) {
|
|
856
921
|
this.mId = mId;
|
|
@@ -1090,640 +1155,534 @@ let Assets = class Assets {
|
|
|
1090
1155
|
};
|
|
1091
1156
|
Assets = __decorate([
|
|
1092
1157
|
injectable(),
|
|
1093
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1158
|
+
scoped(Lifecycle.ContainerScoped),
|
|
1159
|
+
__metadata("design:paramtypes", [MongoConnector, AssetProcessor])
|
|
1094
1160
|
], Assets);
|
|
1095
1161
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
this.
|
|
1100
|
-
this.
|
|
1101
|
-
this.
|
|
1162
|
+
class LazyAsset extends BaseEntity {
|
|
1163
|
+
constructor(id, data, collection, logger, assets, progresses) {
|
|
1164
|
+
super(id, data, collection);
|
|
1165
|
+
this.logger = logger;
|
|
1166
|
+
this.assets = assets;
|
|
1167
|
+
this.progresses = progresses;
|
|
1102
1168
|
}
|
|
1103
|
-
get
|
|
1104
|
-
|
|
1105
|
-
return this.ioServer;
|
|
1169
|
+
get jobName() {
|
|
1170
|
+
return this.data.jobName;
|
|
1106
1171
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
singleton()
|
|
1110
|
-
], BackendProvider);
|
|
1111
|
-
|
|
1112
|
-
let Cache = class Cache {
|
|
1113
|
-
constructor(connector, config, cacheProcessor) {
|
|
1114
|
-
this.connector = connector;
|
|
1115
|
-
this.config = config;
|
|
1116
|
-
this.cacheProcessor = cacheProcessor;
|
|
1172
|
+
get jobParams() {
|
|
1173
|
+
return this.data.jobParams;
|
|
1117
1174
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
return;
|
|
1121
|
-
if (!this.connector.database) {
|
|
1122
|
-
throw new Error(`You can't use cache without mongo connection!`);
|
|
1123
|
-
}
|
|
1124
|
-
this.collection = this.connector.database.collection(this.config.resolve("cacheCollection"));
|
|
1125
|
-
await this.collection.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1175
|
+
get jobQue() {
|
|
1176
|
+
return this.data.jobQue;
|
|
1126
1177
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
const item = {
|
|
1130
|
-
_id: key,
|
|
1131
|
-
data: await this.cacheProcessor.serialize(value),
|
|
1132
|
-
tags: await this.cacheProcessor.serialize(tags),
|
|
1133
|
-
expirationTimestamp,
|
|
1134
|
-
};
|
|
1135
|
-
if (ttl) {
|
|
1136
|
-
const now = Math.round(new Date().getTime() / 1000);
|
|
1137
|
-
item.expiresAt = now + ttl;
|
|
1138
|
-
}
|
|
1139
|
-
await this.collection.updateOne({ _id: key }, { $set: item }, { upsert: true });
|
|
1140
|
-
return value;
|
|
1178
|
+
get progressId() {
|
|
1179
|
+
return this.data.progressId;
|
|
1141
1180
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
if (!item) {
|
|
1150
|
-
throw new Error(`Cache probably doesn't exists with key: ${key}`);
|
|
1181
|
+
get assetId() {
|
|
1182
|
+
return this.data.assetId;
|
|
1183
|
+
}
|
|
1184
|
+
async unlink() {
|
|
1185
|
+
await this.load();
|
|
1186
|
+
if (!this.progressId) {
|
|
1187
|
+
await this.collection.deleteOne({ _id: this.mId });
|
|
1151
1188
|
}
|
|
1152
|
-
return
|
|
1189
|
+
return deleteFromBucket(this.assets.bucket, new ObjectId$1(this.assetId));
|
|
1153
1190
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1191
|
+
startWorking() {
|
|
1192
|
+
this.load().then(() => {
|
|
1193
|
+
if (this.deleted)
|
|
1194
|
+
return;
|
|
1195
|
+
this.progresses.get(this.progressId).then(p => {
|
|
1196
|
+
p?.cancel();
|
|
1197
|
+
});
|
|
1198
|
+
this.startWorkingOnAsset(false).then(() => {
|
|
1199
|
+
this.logger.log("lazy-assets", `Started working on lazy asset: ${this.id}`);
|
|
1200
|
+
}).catch(reason => {
|
|
1201
|
+
this.logger.log("lazy-assets", `Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
|
|
1202
|
+
});
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
async loadAsset() {
|
|
1206
|
+
await this.load();
|
|
1207
|
+
if (this.deleted)
|
|
1208
|
+
return null;
|
|
1209
|
+
if (this.assetId) {
|
|
1210
|
+
return this.assets.read(this.assetId);
|
|
1157
1211
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1212
|
+
if (this.progressId) {
|
|
1213
|
+
await this.progresses.waitToFinish(this.progressId);
|
|
1214
|
+
return this.loadAsset();
|
|
1160
1215
|
}
|
|
1216
|
+
await this.startWorkingOnAsset(true);
|
|
1217
|
+
return this.loadAsset();
|
|
1161
1218
|
}
|
|
1162
|
-
async
|
|
1163
|
-
|
|
1164
|
-
await this.
|
|
1165
|
-
|
|
1166
|
-
};
|
|
1167
|
-
Cache = __decorate([
|
|
1168
|
-
singleton()
|
|
1169
|
-
], Cache);
|
|
1170
|
-
|
|
1171
|
-
let CacheProcessor = class CacheProcessor {
|
|
1172
|
-
async serialize(data) {
|
|
1173
|
-
return data;
|
|
1219
|
+
async writeAsset(asset) {
|
|
1220
|
+
this.data.assetId = asset.id;
|
|
1221
|
+
await this.save();
|
|
1222
|
+
return asset;
|
|
1174
1223
|
}
|
|
1175
|
-
async
|
|
1176
|
-
|
|
1224
|
+
async startWorkingOnAsset(fromLoad) {
|
|
1225
|
+
this.data.progressId = (await this.progresses.create()).id;
|
|
1226
|
+
this.data.assetId = null;
|
|
1227
|
+
await this.save();
|
|
1228
|
+
await this.progresses.jobMan.enqueueWithName(this.data.jobName, { ...this.data.jobParams, lazyId: this.id, fromLoad });
|
|
1177
1229
|
}
|
|
1178
|
-
}
|
|
1179
|
-
CacheProcessor = __decorate([
|
|
1180
|
-
injectable(),
|
|
1181
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1182
|
-
], CacheProcessor);
|
|
1230
|
+
}
|
|
1183
1231
|
|
|
1184
|
-
let
|
|
1185
|
-
constructor(
|
|
1186
|
-
|
|
1187
|
-
this.
|
|
1188
|
-
this.
|
|
1189
|
-
(params || []).forEach(param => this.add(param));
|
|
1232
|
+
let Logger = class Logger {
|
|
1233
|
+
constructor(config) {
|
|
1234
|
+
this.config = config;
|
|
1235
|
+
this.tags = this.config.resolve("logTags");
|
|
1236
|
+
this.ignoredTags = this.config.resolve("ignoredLogTags");
|
|
1190
1237
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1238
|
+
log(tag, ...params) {
|
|
1239
|
+
if (this.ignoredTags.includes(tag))
|
|
1240
|
+
return;
|
|
1241
|
+
if (this.tags.length === 0 || this.tags.includes(tag)) {
|
|
1242
|
+
console.log(`[${tag}]`, ...params);
|
|
1243
|
+
}
|
|
1196
1244
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1245
|
+
};
|
|
1246
|
+
Logger = __decorate([
|
|
1247
|
+
singleton(),
|
|
1248
|
+
__metadata("design:paramtypes", [Configuration])
|
|
1249
|
+
], Logger);
|
|
1250
|
+
|
|
1251
|
+
let JobManager = class JobManager {
|
|
1252
|
+
constructor(config, logger, container, jobTypes) {
|
|
1253
|
+
this.config = config;
|
|
1254
|
+
this.logger = logger;
|
|
1255
|
+
this.container = container;
|
|
1256
|
+
this.jobTypes = jobTypes || [];
|
|
1257
|
+
this.jobs = this.jobTypes.reduce((res, jobType) => {
|
|
1258
|
+
const jobName = getConstructorName(jobType);
|
|
1259
|
+
res[jobName] = (jobParams, uniqueId) => {
|
|
1260
|
+
const job = this.resolveJobInstance(jobType, jobParams, uniqueId);
|
|
1261
|
+
const messageBridge = {
|
|
1262
|
+
sendMessage: (message, params) => {
|
|
1263
|
+
params.uniqueId = uniqueId;
|
|
1264
|
+
this.workerPush.send([message, JSON.stringify(params)]);
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
messageBridge.sendMessage(`job-started`, { name: jobName });
|
|
1268
|
+
return job.process(messageBridge);
|
|
1269
|
+
};
|
|
1270
|
+
return res;
|
|
1271
|
+
}, {});
|
|
1272
|
+
this.messages = new Subject();
|
|
1273
|
+
this.processing = false;
|
|
1274
|
+
this.maxTimeout = this.config.resolve("jobTimeout");
|
|
1275
|
+
}
|
|
1276
|
+
on(message, cb) {
|
|
1277
|
+
return this.messages
|
|
1278
|
+
.pipe(filter$1(t => t.message === message))
|
|
1279
|
+
.pipe(map(t => t.params)).subscribe(cb);
|
|
1280
|
+
}
|
|
1281
|
+
async process(jobType, params = {}) {
|
|
1282
|
+
let instance = null;
|
|
1283
|
+
try {
|
|
1284
|
+
instance = this.resolveJobInstance(jobType, params);
|
|
1209
1285
|
}
|
|
1210
|
-
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1213
|
-
return value;
|
|
1286
|
+
catch (e) {
|
|
1287
|
+
const jobName = getConstructorName(jobType);
|
|
1288
|
+
throw new Error(`Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`);
|
|
1214
1289
|
}
|
|
1215
|
-
|
|
1216
|
-
return param.defaultValue;
|
|
1290
|
+
return instance.process();
|
|
1217
1291
|
}
|
|
1218
|
-
|
|
1219
|
-
return
|
|
1292
|
+
async enqueueWithName(name, params = {}) {
|
|
1293
|
+
return this.sendToWorkers(this.tryResolveFromName(name, params), params);
|
|
1220
1294
|
}
|
|
1221
|
-
|
|
1222
|
-
return this.
|
|
1295
|
+
async enqueue(jobType, params = {}) {
|
|
1296
|
+
return this.sendToWorkers(this.tryResolveAndInit(jobType, params), params);
|
|
1223
1297
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1298
|
+
schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}) {
|
|
1299
|
+
const expression = [minute, hour, dayOfMonth, month, dayOfWeek].map(t => {
|
|
1300
|
+
if (isObject(t)) {
|
|
1301
|
+
const range = t;
|
|
1302
|
+
return `${range.min || 0}-${range.max || 0}`;
|
|
1303
|
+
}
|
|
1304
|
+
if (isArray(t)) {
|
|
1305
|
+
return t.join(",");
|
|
1306
|
+
}
|
|
1307
|
+
return `${t}`;
|
|
1308
|
+
}).join(" ");
|
|
1309
|
+
const jobName = getConstructorName(jobType);
|
|
1310
|
+
if (!cron.validate(expression)) {
|
|
1311
|
+
this.logger.log("job-manager", `Can't schedule the task: '${jobName}' because time expression is invalid.`);
|
|
1312
|
+
return null;
|
|
1227
1313
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1314
|
+
return cron.schedule(expression, () => {
|
|
1315
|
+
this.enqueue(jobType, params).catch(e => {
|
|
1316
|
+
this.logger.log("job-manager", `Can't enqueue job: '${jobName}' because: ${e}`);
|
|
1317
|
+
});
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
async startProcessing() {
|
|
1321
|
+
if (this.processing)
|
|
1322
|
+
return null;
|
|
1323
|
+
this.processing = true;
|
|
1324
|
+
if (!this.config.resolve("isWorker")) {
|
|
1325
|
+
this.logger.log("job-manager", colorize(`Processing can not be started because this is NOT a worker process!`, ConsoleColor.FgRed));
|
|
1326
|
+
return null;
|
|
1234
1327
|
}
|
|
1235
|
-
|
|
1328
|
+
const host = this.config.resolve("zmqRemoteHost");
|
|
1329
|
+
const pushHost = `${host}:${this.config.resolve("zmqBackPort")}`;
|
|
1330
|
+
this.workerPush = socket("push");
|
|
1331
|
+
await this.workerPush.connect(pushHost);
|
|
1332
|
+
this.logger.log("job-manager", `Worker producer connected to: ${pushHost}`);
|
|
1333
|
+
const pullHost = `${host}:${this.config.resolve("zmqPort")}`;
|
|
1334
|
+
this.workerPull = socket("pull");
|
|
1335
|
+
await this.workerPull.connect(pullHost);
|
|
1336
|
+
this.logger.log("job-manager", `Worker consumer connected to: ${pullHost}`);
|
|
1337
|
+
this.workerPull.on("message", async (name, args, uniqId) => {
|
|
1338
|
+
try {
|
|
1339
|
+
const jobName = name.toString("utf8");
|
|
1340
|
+
const jobParams = JSON.parse(args.toString("utf8"));
|
|
1341
|
+
const uniqueId = uniqId?.toString("utf8");
|
|
1342
|
+
console.time(uniqueId);
|
|
1343
|
+
console.timeLog(uniqueId, `Started working on background job: ${colorize(jobName, ConsoleColor.FgCyan)} with args: \n${jsonHighlight(jobParams)}\n\n`);
|
|
1344
|
+
try {
|
|
1345
|
+
await Promise.race([this.jobs[jobName](jobParams, uniqueId), promiseTimeout(this.maxTimeout, true)]);
|
|
1346
|
+
console.timeLog(uniqueId, `Finished working on background job: ${colorize(jobName, ConsoleColor.FgCyan)}\n\n`);
|
|
1347
|
+
}
|
|
1348
|
+
catch (e) {
|
|
1349
|
+
console.timeLog(uniqueId, `Background job failed: ${colorize(jobName, ConsoleColor.FgRed)}\n${e}\n\n`);
|
|
1350
|
+
}
|
|
1351
|
+
console.timeEnd(uniqueId);
|
|
1352
|
+
}
|
|
1353
|
+
catch (e) {
|
|
1354
|
+
this.logger.log("job-manager", `Failed to start job: ${e.message}`);
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1236
1357
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1358
|
+
tryResolve(jobType, params) {
|
|
1359
|
+
const jobName = getConstructorName(jobType);
|
|
1360
|
+
if (!this.jobs[jobName]) {
|
|
1361
|
+
throw `Can't find job with name: ${jobName} so it can't be enqueued!`;
|
|
1362
|
+
}
|
|
1363
|
+
try {
|
|
1364
|
+
this.resolveJobInstance(jobType, params);
|
|
1365
|
+
}
|
|
1366
|
+
catch (e) {
|
|
1367
|
+
throw `Can't resolve params for job: ${jobName}, with params: ${JSON.stringify(params)}. Reason: ${e}`;
|
|
1368
|
+
}
|
|
1369
|
+
return jobName;
|
|
1246
1370
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
this.fixtures = fixtures;
|
|
1371
|
+
tryResolveFromName(jobName, params) {
|
|
1372
|
+
const jobType = this.jobTypes.find(type => {
|
|
1373
|
+
return getConstructorName(type) == jobName;
|
|
1374
|
+
});
|
|
1375
|
+
if (!jobType) {
|
|
1376
|
+
throw `Can't find job type with name: ${jobName} so it can't be enqueued!`;
|
|
1377
|
+
}
|
|
1378
|
+
return this.tryResolveAndInit(jobType, params);
|
|
1256
1379
|
}
|
|
1257
|
-
|
|
1258
|
-
if (!this.
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1380
|
+
tryResolveAndInit(jobType, params) {
|
|
1381
|
+
if (!this.apiPush) {
|
|
1382
|
+
const port = this.config.resolve("zmqPort");
|
|
1383
|
+
this.apiPush = socket("push");
|
|
1384
|
+
this.apiPush.bind(`tcp://0.0.0.0:${port}`);
|
|
1385
|
+
this.logger.log("job-manager", `API producer bound to port: ${port}`);
|
|
1386
|
+
}
|
|
1387
|
+
if (!this.apiPull) {
|
|
1388
|
+
const backPort = this.config.resolve("zmqBackPort");
|
|
1389
|
+
this.apiPull = socket("pull");
|
|
1390
|
+
this.apiPull.bind(`tcp://0.0.0.0:${backPort}`);
|
|
1391
|
+
this.apiPull.on("message", (name, args) => {
|
|
1392
|
+
const message = name.toString("utf8");
|
|
1393
|
+
const params = JSON.parse(args?.toString("utf8") || "{}");
|
|
1394
|
+
const paramTypes = Object.keys(params).reduce((res, key) => {
|
|
1395
|
+
res[key] = getType(params[key]);
|
|
1396
|
+
return res;
|
|
1397
|
+
}, {});
|
|
1398
|
+
this.logger.log("job-manager", `Received a message from worker: "${colorize(message, ConsoleColor.FgCyan)}" with args: ${jsonHighlight(paramTypes)}\n\n`);
|
|
1399
|
+
this.messages.next({ message, params });
|
|
1400
|
+
});
|
|
1401
|
+
this.logger.log("job-manager", `API consumer bound to port: ${backPort}`);
|
|
1266
1402
|
}
|
|
1403
|
+
return this.tryResolve(jobType, params);
|
|
1404
|
+
}
|
|
1405
|
+
resolveJobInstance(jobType, params, uniqueId = "") {
|
|
1406
|
+
const container = this.container.createChildContainer();
|
|
1407
|
+
Object.keys(params).map((name) => {
|
|
1408
|
+
container.register(name, { useValue: params[name] });
|
|
1409
|
+
});
|
|
1410
|
+
container.register("uniqueId", { useValue: uniqueId });
|
|
1411
|
+
container.register(jobType, jobType);
|
|
1412
|
+
return container.resolve(jobType);
|
|
1413
|
+
}
|
|
1414
|
+
async sendToWorkers(jobName, params) {
|
|
1415
|
+
const publisher = await this.apiPush;
|
|
1416
|
+
const uniqueId = new ObjectId$1().toHexString();
|
|
1417
|
+
await publisher.send([jobName, JSON.stringify(params), uniqueId]);
|
|
1418
|
+
return uniqueId;
|
|
1267
1419
|
}
|
|
1268
1420
|
};
|
|
1269
|
-
|
|
1421
|
+
JobManager = __decorate([
|
|
1270
1422
|
injectable(),
|
|
1271
1423
|
scoped(Lifecycle.ContainerScoped),
|
|
1272
|
-
__param(
|
|
1273
|
-
|
|
1424
|
+
__param(2, inject(DI_CONTAINER)),
|
|
1425
|
+
__param(3, injectAll(JOB)),
|
|
1426
|
+
__metadata("design:paramtypes", [Configuration,
|
|
1427
|
+
Logger, Object, Array])
|
|
1428
|
+
], JobManager);
|
|
1274
1429
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
this.config = config;
|
|
1279
|
-
this.galleryCache = galleryCache;
|
|
1280
|
-
this.cache = {};
|
|
1281
|
-
this.dir = this.config.resolve("galleryDir");
|
|
1282
|
-
this.output = join(this.config.resolve("cacheDir"), "gallery");
|
|
1283
|
-
}
|
|
1284
|
-
async getFolder(folder, size = null) {
|
|
1285
|
-
this.cache[folder] = this.cache[folder] || new Promise(resolve => {
|
|
1286
|
-
lstat(join(this.dir, folder), (err, stats) => {
|
|
1287
|
-
if (err || !stats.isDirectory()) {
|
|
1288
|
-
resolve([]);
|
|
1289
|
-
return;
|
|
1290
|
-
}
|
|
1291
|
-
this.readRecursive(folder, "", size).then(resolve, () => resolve([]));
|
|
1292
|
-
});
|
|
1293
|
-
});
|
|
1294
|
-
return this.cache[folder];
|
|
1430
|
+
class Progress extends BaseEntity {
|
|
1431
|
+
constructor(id, data, collection) {
|
|
1432
|
+
super(id, data, collection);
|
|
1295
1433
|
}
|
|
1296
|
-
|
|
1297
|
-
return
|
|
1298
|
-
readdir(join(this.dir, path), (err, files) => {
|
|
1299
|
-
if (err) {
|
|
1300
|
-
resolve([]);
|
|
1301
|
-
return;
|
|
1302
|
-
}
|
|
1303
|
-
const promises = files.map(file => {
|
|
1304
|
-
return new Promise(async (resolve) => {
|
|
1305
|
-
const filePath = join(path, file);
|
|
1306
|
-
const absoluteFilePath = join(this.dir, filePath);
|
|
1307
|
-
lstat(absoluteFilePath, (err, stats) => {
|
|
1308
|
-
if (err) {
|
|
1309
|
-
resolve([]);
|
|
1310
|
-
return;
|
|
1311
|
-
}
|
|
1312
|
-
if (stats.isDirectory()) {
|
|
1313
|
-
this.readRecursive(filePath, join(folder, file), size).then(resolve);
|
|
1314
|
-
return;
|
|
1315
|
-
}
|
|
1316
|
-
const sharpImg = sharp$1(absoluteFilePath);
|
|
1317
|
-
sharpImg.rotate().metadata().then(() => {
|
|
1318
|
-
const getResultPath = (isThumb) => {
|
|
1319
|
-
return join(this.output, filePath.replace(/.([a-z|A-Z]+)$/gi, function (ext) {
|
|
1320
|
-
const suffix = isThumb ? 'thumb' : 'big';
|
|
1321
|
-
return `-${suffix}${ext}`;
|
|
1322
|
-
}));
|
|
1323
|
-
};
|
|
1324
|
-
resolve([this.galleryCache.create(folder, size, {
|
|
1325
|
-
getOriginal: () => {
|
|
1326
|
-
return new Promise((res, rej) => {
|
|
1327
|
-
readFile$1(absoluteFilePath, (err, data) => {
|
|
1328
|
-
if (err) {
|
|
1329
|
-
rej(err);
|
|
1330
|
-
return;
|
|
1331
|
-
}
|
|
1332
|
-
res(data);
|
|
1333
|
-
});
|
|
1334
|
-
});
|
|
1335
|
-
},
|
|
1336
|
-
writeResult: (isThumb, buffer) => {
|
|
1337
|
-
return new Promise(async (res, rej) => {
|
|
1338
|
-
const resultPath = getResultPath(isThumb);
|
|
1339
|
-
await mkdirRecursive(dirname(resultPath));
|
|
1340
|
-
writeFile$1(resultPath, buffer, err => {
|
|
1341
|
-
if (err) {
|
|
1342
|
-
rej(err);
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
|
-
res();
|
|
1346
|
-
});
|
|
1347
|
-
});
|
|
1348
|
-
},
|
|
1349
|
-
hasResult: (isThumb) => {
|
|
1350
|
-
return new Promise(res => {
|
|
1351
|
-
access(getResultPath(isThumb), constants.R_OK, err => {
|
|
1352
|
-
res(!err);
|
|
1353
|
-
});
|
|
1354
|
-
});
|
|
1355
|
-
},
|
|
1356
|
-
serveResult: (isThumb) => {
|
|
1357
|
-
return new Promise((res, rej) => {
|
|
1358
|
-
readFile$1(getResultPath(isThumb), (err, data) => {
|
|
1359
|
-
if (err) {
|
|
1360
|
-
rej(err);
|
|
1361
|
-
return;
|
|
1362
|
-
}
|
|
1363
|
-
res(data);
|
|
1364
|
-
});
|
|
1365
|
-
});
|
|
1366
|
-
}
|
|
1367
|
-
})]);
|
|
1368
|
-
}, () => resolve([]));
|
|
1369
|
-
});
|
|
1370
|
-
});
|
|
1371
|
-
});
|
|
1372
|
-
Promise.all(promises).then(folders => {
|
|
1373
|
-
resolve([].concat.apply([], folders));
|
|
1374
|
-
});
|
|
1375
|
-
});
|
|
1376
|
-
});
|
|
1434
|
+
get current() {
|
|
1435
|
+
return this.data.current;
|
|
1377
1436
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
injectable(),
|
|
1381
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1382
|
-
], Gallery);
|
|
1383
|
-
|
|
1384
|
-
const sharp = sharp_;
|
|
1385
|
-
const bigSize = 1500;
|
|
1386
|
-
const thumbSize = 250;
|
|
1387
|
-
class GalleryImage {
|
|
1388
|
-
constructor(folder, size, handler) {
|
|
1389
|
-
this.folder = folder;
|
|
1390
|
-
this.handler = handler;
|
|
1391
|
-
this.thumb = v4();
|
|
1392
|
-
this.big = v4();
|
|
1393
|
-
this.targetSize = !size ? { width: thumbSize, height: thumbSize } : size;
|
|
1437
|
+
get max() {
|
|
1438
|
+
return this.data.max;
|
|
1394
1439
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
if (await this.handler.hasResult(isThumb)) {
|
|
1398
|
-
return this.handler.serveResult(isThumb);
|
|
1399
|
-
}
|
|
1400
|
-
const original = sharp(await this.handler.getOriginal()).rotate();
|
|
1401
|
-
const meta = await original.metadata();
|
|
1402
|
-
const ratio = meta.width / meta.height;
|
|
1403
|
-
const sizeRatio = isThumb ? this.targetSize.width / this.targetSize.height : 1;
|
|
1404
|
-
const size = isThumb ? Math.max(this.targetSize.width, this.targetSize.height) : bigSize;
|
|
1405
|
-
const targetHeight = ratio > sizeRatio ? size : Math.round(size / ratio);
|
|
1406
|
-
const targetWidth = Math.round(targetHeight * ratio);
|
|
1407
|
-
const resized = original.resize(targetWidth, targetHeight);
|
|
1408
|
-
const buffer = await (isThumb ? resized.extract({
|
|
1409
|
-
left: Math.floor((targetWidth - this.targetSize.width) / 2),
|
|
1410
|
-
top: Math.floor((targetHeight - this.targetSize.height) / 2),
|
|
1411
|
-
width: this.targetSize.width,
|
|
1412
|
-
height: this.targetSize.height
|
|
1413
|
-
}).toBuffer() : resized.toBuffer());
|
|
1414
|
-
await this.handler.writeResult(isThumb, buffer);
|
|
1415
|
-
return this.handler.serveResult(isThumb);
|
|
1440
|
+
get message() {
|
|
1441
|
+
return this.data.message;
|
|
1416
1442
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
let GalleryCache = class GalleryCache {
|
|
1420
|
-
constructor() {
|
|
1421
|
-
this.imgCache = {};
|
|
1443
|
+
get error() {
|
|
1444
|
+
return this.data.error;
|
|
1422
1445
|
}
|
|
1423
|
-
|
|
1424
|
-
this.
|
|
1425
|
-
this.imgCache[img.big] = img;
|
|
1446
|
+
get canceled() {
|
|
1447
|
+
return this.data.canceled;
|
|
1426
1448
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
return !img ? null : img.serve(id);
|
|
1449
|
+
get percent() {
|
|
1450
|
+
return this.max > 0 ? Math.round(this.current / this.max * 100) : 0;
|
|
1430
1451
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
this.put(image);
|
|
1434
|
-
return image;
|
|
1452
|
+
get remaining() {
|
|
1453
|
+
return this.max > 0 ? this.max - this.current : 0;
|
|
1435
1454
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1440
|
-
], GalleryCache);
|
|
1441
|
-
|
|
1442
|
-
let IdGenerator = class IdGenerator {
|
|
1443
|
-
constructor(config) {
|
|
1444
|
-
this.config = config;
|
|
1445
|
-
this.prefix = config.resolve("idPrefix");
|
|
1446
|
-
this.separator = config.resolve("idSeparator");
|
|
1447
|
-
this.chars = config.resolve("idChars");
|
|
1448
|
-
this.parts = config.resolve("idParts");
|
|
1455
|
+
setMessageBridge(messageBridge) {
|
|
1456
|
+
this.messageBridge = messageBridge || this.messageBridge;
|
|
1457
|
+
return this;
|
|
1449
1458
|
}
|
|
1450
|
-
async
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
let notGood = true;
|
|
1454
|
-
while (notGood && tries < 5) {
|
|
1455
|
-
id = this.generateId();
|
|
1456
|
-
notGood = await checkCb(id);
|
|
1457
|
-
tries++;
|
|
1459
|
+
async createSubProgress(progressValue, max, message) {
|
|
1460
|
+
if (max <= 0 && progressValue > 0) {
|
|
1461
|
+
await this.advance(progressValue);
|
|
1458
1462
|
}
|
|
1459
|
-
if (
|
|
1460
|
-
|
|
1463
|
+
if (message !== null) {
|
|
1464
|
+
this.data.message = message;
|
|
1465
|
+
await this.save();
|
|
1461
1466
|
}
|
|
1462
|
-
return
|
|
1467
|
+
return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
|
|
1463
1468
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
}
|
|
1471
|
-
return s;
|
|
1472
|
-
}).join(this.separator);
|
|
1469
|
+
async setMax(max) {
|
|
1470
|
+
if (isNaN(max) || max <= 0) {
|
|
1471
|
+
throw "Max progress value must be bigger than zero";
|
|
1472
|
+
}
|
|
1473
|
+
this.data.max = max;
|
|
1474
|
+
await this.save();
|
|
1473
1475
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1478
|
-
], IdGenerator);
|
|
1479
|
-
|
|
1480
|
-
let JobManager = class JobManager {
|
|
1481
|
-
constructor(config, logger, container, jobTypes) {
|
|
1482
|
-
this.config = config;
|
|
1483
|
-
this.logger = logger;
|
|
1484
|
-
this.container = container;
|
|
1485
|
-
this.jobTypes = jobTypes || [];
|
|
1486
|
-
this.jobs = this.jobTypes.reduce((res, jobType) => {
|
|
1487
|
-
const jobName = getConstructorName(jobType);
|
|
1488
|
-
res[jobName] = (jobParams, uniqueId) => {
|
|
1489
|
-
const job = this.resolveJobInstance(jobType, jobParams, uniqueId);
|
|
1490
|
-
const messageBridge = {
|
|
1491
|
-
sendMessage: (message, params) => {
|
|
1492
|
-
params.uniqueId = uniqueId;
|
|
1493
|
-
this.workerPush.send([message, JSON.stringify(params)]);
|
|
1494
|
-
}
|
|
1495
|
-
};
|
|
1496
|
-
messageBridge.sendMessage(`job-started`, { name: jobName });
|
|
1497
|
-
return job.process(messageBridge);
|
|
1498
|
-
};
|
|
1499
|
-
return res;
|
|
1500
|
-
}, {});
|
|
1501
|
-
this.messages = new Subject();
|
|
1502
|
-
this.processing = false;
|
|
1503
|
-
this.maxTimeout = this.config.resolve("jobTimeout");
|
|
1476
|
+
async setMessage(message) {
|
|
1477
|
+
this.data.message = message;
|
|
1478
|
+
await this.save();
|
|
1504
1479
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
.pipe(map(t => t.params)).subscribe(cb);
|
|
1480
|
+
async setError(error) {
|
|
1481
|
+
this.data.error = error;
|
|
1482
|
+
await this.save();
|
|
1509
1483
|
}
|
|
1510
|
-
async
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
instance = this.resolveJobInstance(jobType, params);
|
|
1484
|
+
async advance(value = 1) {
|
|
1485
|
+
if (isNaN(value) || value <= 0) {
|
|
1486
|
+
throw new Error(`Advance value must be bigger than zero: ${this.id}`);
|
|
1514
1487
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1488
|
+
await this.load();
|
|
1489
|
+
if (this.deleted || this.canceled) {
|
|
1490
|
+
const status = this.deleted ? "deleted" : "canceled";
|
|
1491
|
+
throw new Error(`Can't advance ${status} progress: ${this.id}`);
|
|
1518
1492
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
async enqueueWithName(name, params = {}) {
|
|
1522
|
-
return this.sendToWorkers(this.tryResolveFromName(name, params), params);
|
|
1523
|
-
}
|
|
1524
|
-
async enqueue(jobType, params = {}) {
|
|
1525
|
-
return this.sendToWorkers(this.tryResolveAndInit(jobType, params), params);
|
|
1493
|
+
this.data.current = Math.min(this.max, this.current + value);
|
|
1494
|
+
await this.save();
|
|
1526
1495
|
}
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
const range = t;
|
|
1531
|
-
return `${range.min || 0}-${range.max || 0}`;
|
|
1532
|
-
}
|
|
1533
|
-
if (isArray(t)) {
|
|
1534
|
-
return t.join(",");
|
|
1535
|
-
}
|
|
1536
|
-
return `${t}`;
|
|
1537
|
-
}).join(" ");
|
|
1538
|
-
const jobName = getConstructorName(jobType);
|
|
1539
|
-
if (!cron.validate(expression)) {
|
|
1540
|
-
this.logger.log("job-manager", `Can't schedule the task: '${jobName}' because time expression is invalid.`);
|
|
1541
|
-
return null;
|
|
1542
|
-
}
|
|
1543
|
-
return cron.schedule(expression, () => {
|
|
1544
|
-
this.enqueue(jobType, params).catch(e => {
|
|
1545
|
-
this.logger.log("job-manager", `Can't enqueue job: '${jobName}' because: ${e}`);
|
|
1546
|
-
});
|
|
1547
|
-
});
|
|
1496
|
+
async cancel() {
|
|
1497
|
+
this.data.canceled = true;
|
|
1498
|
+
await this.save();
|
|
1548
1499
|
}
|
|
1549
|
-
|
|
1550
|
-
if (this.
|
|
1551
|
-
|
|
1552
|
-
this.processing = true;
|
|
1553
|
-
if (!this.config.resolve("isWorker")) {
|
|
1554
|
-
this.logger.log("job-manager", colorize(`Processing can not be started because this is NOT a worker process!`, ConsoleColor.FgRed));
|
|
1555
|
-
return null;
|
|
1500
|
+
save() {
|
|
1501
|
+
if (this.messageBridge) {
|
|
1502
|
+
this.messageBridge.sendMessage(`progress-changed`, this.toJSON());
|
|
1556
1503
|
}
|
|
1557
|
-
|
|
1558
|
-
const pushHost = `${host}:${this.config.resolve("zmqBackPort")}`;
|
|
1559
|
-
this.workerPush = socket("push");
|
|
1560
|
-
await this.workerPush.connect(pushHost);
|
|
1561
|
-
this.logger.log("job-manager", `Worker producer connected to: ${pushHost}`);
|
|
1562
|
-
const pullHost = `${host}:${this.config.resolve("zmqPort")}`;
|
|
1563
|
-
this.workerPull = socket("pull");
|
|
1564
|
-
await this.workerPull.connect(pullHost);
|
|
1565
|
-
this.logger.log("job-manager", `Worker consumer connected to: ${pullHost}`);
|
|
1566
|
-
this.workerPull.on("message", async (name, args, uniqId) => {
|
|
1567
|
-
try {
|
|
1568
|
-
const jobName = name.toString("utf8");
|
|
1569
|
-
const jobParams = JSON.parse(args.toString("utf8"));
|
|
1570
|
-
const uniqueId = uniqId?.toString("utf8");
|
|
1571
|
-
console.time(uniqueId);
|
|
1572
|
-
console.timeLog(uniqueId, `Started working on background job: ${colorize(jobName, ConsoleColor.FgCyan)} with args: \n${jsonHighlight(jobParams)}\n\n`);
|
|
1573
|
-
try {
|
|
1574
|
-
await Promise.race([this.jobs[jobName](jobParams, uniqueId), promiseTimeout(this.maxTimeout, true)]);
|
|
1575
|
-
console.timeLog(uniqueId, `Finished working on background job: ${colorize(jobName, ConsoleColor.FgCyan)}\n\n`);
|
|
1576
|
-
}
|
|
1577
|
-
catch (e) {
|
|
1578
|
-
console.timeLog(uniqueId, `Background job failed: ${colorize(jobName, ConsoleColor.FgRed)}\n${e}\n\n`);
|
|
1579
|
-
}
|
|
1580
|
-
console.timeEnd(uniqueId);
|
|
1581
|
-
}
|
|
1582
|
-
catch (e) {
|
|
1583
|
-
this.logger.log("job-manager", `Failed to start job: ${e.message}`);
|
|
1584
|
-
}
|
|
1585
|
-
});
|
|
1504
|
+
return super.save();
|
|
1586
1505
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1506
|
+
}
|
|
1507
|
+
class SubProgress {
|
|
1508
|
+
constructor(parent, progressFrom, progressValue, mMax = 100) {
|
|
1509
|
+
this.parent = parent;
|
|
1510
|
+
this.progressFrom = progressFrom;
|
|
1511
|
+
this.progressValue = progressValue;
|
|
1512
|
+
this.mMax = mMax;
|
|
1513
|
+
if (progressFrom < 0) {
|
|
1514
|
+
throw "Progress from must be bigger than or zero";
|
|
1594
1515
|
}
|
|
1595
|
-
|
|
1596
|
-
throw
|
|
1516
|
+
if (progressValue <= 0) {
|
|
1517
|
+
throw "Progress value must be bigger than zero";
|
|
1597
1518
|
}
|
|
1598
|
-
|
|
1519
|
+
this.mCurrent = 0;
|
|
1599
1520
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
return getConstructorName(type) == jobName;
|
|
1603
|
-
});
|
|
1604
|
-
if (!jobType) {
|
|
1605
|
-
throw `Can't find job type with name: ${jobName} so it can't be enqueued!`;
|
|
1606
|
-
}
|
|
1607
|
-
return this.tryResolveAndInit(jobType, params);
|
|
1521
|
+
get id() {
|
|
1522
|
+
return this.parent.id;
|
|
1608
1523
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
const port = this.config.resolve("zmqPort");
|
|
1612
|
-
this.apiPush = socket("push");
|
|
1613
|
-
this.apiPush.bind(`tcp://0.0.0.0:${port}`);
|
|
1614
|
-
this.logger.log("job-manager", `API producer bound to port: ${port}`);
|
|
1615
|
-
}
|
|
1616
|
-
if (!this.apiPull) {
|
|
1617
|
-
const backPort = this.config.resolve("zmqBackPort");
|
|
1618
|
-
this.apiPull = socket("pull");
|
|
1619
|
-
this.apiPull.bind(`tcp://0.0.0.0:${backPort}`);
|
|
1620
|
-
this.apiPull.on("message", (name, args) => {
|
|
1621
|
-
const message = name.toString("utf8");
|
|
1622
|
-
const params = JSON.parse(args?.toString("utf8") || "{}");
|
|
1623
|
-
const paramTypes = Object.keys(params).reduce((res, key) => {
|
|
1624
|
-
res[key] = getType(params[key]);
|
|
1625
|
-
return res;
|
|
1626
|
-
}, {});
|
|
1627
|
-
this.logger.log("job-manager", `Received a message from worker: "${colorize(message, ConsoleColor.FgCyan)}" with args: ${jsonHighlight(paramTypes)}\n\n`);
|
|
1628
|
-
this.messages.next({ message, params });
|
|
1629
|
-
});
|
|
1630
|
-
this.logger.log("job-manager", `API consumer bound to port: ${backPort}`);
|
|
1631
|
-
}
|
|
1632
|
-
return this.tryResolve(jobType, params);
|
|
1524
|
+
get current() {
|
|
1525
|
+
return this.mCurrent;
|
|
1633
1526
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
Object.keys(params).map((name) => {
|
|
1637
|
-
container.register(name, { useValue: params[name] });
|
|
1638
|
-
});
|
|
1639
|
-
container.register("uniqueId", { useValue: uniqueId });
|
|
1640
|
-
container.register(jobType, jobType);
|
|
1641
|
-
return container.resolve(jobType);
|
|
1527
|
+
get max() {
|
|
1528
|
+
return this.mMax;
|
|
1642
1529
|
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
const uniqueId = new ObjectId$1().toHexString();
|
|
1646
|
-
await publisher.send([jobName, JSON.stringify(params), uniqueId]);
|
|
1647
|
-
return uniqueId;
|
|
1530
|
+
get message() {
|
|
1531
|
+
return this.parent.message;
|
|
1648
1532
|
}
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
injectable(),
|
|
1652
|
-
scoped(Lifecycle.ContainerScoped),
|
|
1653
|
-
__param(2, inject(DI_CONTAINER)),
|
|
1654
|
-
__param(3, injectAll(JOB))
|
|
1655
|
-
], JobManager);
|
|
1656
|
-
|
|
1657
|
-
class LazyAsset extends BaseEntity {
|
|
1658
|
-
constructor(id, data, collection, logger, assets, progresses) {
|
|
1659
|
-
super(id, data, collection);
|
|
1660
|
-
this.logger = logger;
|
|
1661
|
-
this.assets = assets;
|
|
1662
|
-
this.progresses = progresses;
|
|
1533
|
+
get error() {
|
|
1534
|
+
return this.parent.error;
|
|
1663
1535
|
}
|
|
1664
|
-
get
|
|
1665
|
-
return this.
|
|
1536
|
+
get percent() {
|
|
1537
|
+
return this.parent.percent;
|
|
1666
1538
|
}
|
|
1667
|
-
get
|
|
1668
|
-
return this.
|
|
1539
|
+
get remaining() {
|
|
1540
|
+
return this.max - this.mCurrent;
|
|
1669
1541
|
}
|
|
1670
|
-
get
|
|
1671
|
-
return this.
|
|
1542
|
+
get canceled() {
|
|
1543
|
+
return !this.parent || this.parent.canceled;
|
|
1672
1544
|
}
|
|
1673
|
-
|
|
1674
|
-
|
|
1545
|
+
setMessageBridge(messageBridge) {
|
|
1546
|
+
if (!this.parent)
|
|
1547
|
+
return this;
|
|
1548
|
+
this.parent.setMessageBridge(messageBridge);
|
|
1549
|
+
return this;
|
|
1675
1550
|
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1551
|
+
async createSubProgress(progressValue, max, message) {
|
|
1552
|
+
if (max <= 0 && progressValue > 0) {
|
|
1553
|
+
await this.advance(progressValue);
|
|
1554
|
+
}
|
|
1555
|
+
if (message !== null) {
|
|
1556
|
+
await this.setMessage(message);
|
|
1557
|
+
}
|
|
1558
|
+
return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
|
|
1678
1559
|
}
|
|
1679
|
-
async
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
await this.collection.deleteOne({ _id: this.mId });
|
|
1560
|
+
async setMax(max) {
|
|
1561
|
+
if (isNaN(max) || max <= 0) {
|
|
1562
|
+
throw "Max progress value must be bigger than zero";
|
|
1683
1563
|
}
|
|
1684
|
-
|
|
1564
|
+
this.mMax = max;
|
|
1565
|
+
await this.save();
|
|
1685
1566
|
}
|
|
1686
|
-
|
|
1687
|
-
this.
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
this.progresses.get(this.progressId).then(p => {
|
|
1691
|
-
p?.cancel();
|
|
1692
|
-
});
|
|
1693
|
-
this.startWorkingOnAsset(false).then(() => {
|
|
1694
|
-
this.logger.log("lazy-assets", `Started working on lazy asset: ${this.id}`);
|
|
1695
|
-
}).catch(reason => {
|
|
1696
|
-
this.logger.log("lazy-assets", `Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
|
|
1697
|
-
});
|
|
1698
|
-
});
|
|
1567
|
+
async setMessage(message) {
|
|
1568
|
+
if (!this.parent)
|
|
1569
|
+
return null;
|
|
1570
|
+
await this.parent.setMessage(message);
|
|
1699
1571
|
}
|
|
1700
|
-
async
|
|
1701
|
-
|
|
1702
|
-
if (this.deleted)
|
|
1572
|
+
async setError(error) {
|
|
1573
|
+
if (!this.parent)
|
|
1703
1574
|
return null;
|
|
1704
|
-
|
|
1705
|
-
return this.assets.read(this.assetId);
|
|
1706
|
-
}
|
|
1707
|
-
if (this.progressId) {
|
|
1708
|
-
await this.progresses.waitToFinish(this.progressId);
|
|
1709
|
-
return this.loadAsset();
|
|
1710
|
-
}
|
|
1711
|
-
await this.startWorkingOnAsset(true);
|
|
1712
|
-
return this.loadAsset();
|
|
1575
|
+
await this.parent.setError(error);
|
|
1713
1576
|
}
|
|
1714
|
-
async
|
|
1715
|
-
|
|
1577
|
+
async advance(value = 1) {
|
|
1578
|
+
if (isNaN(value) || value <= 0) {
|
|
1579
|
+
throw "Advance value must be bigger than zero";
|
|
1580
|
+
}
|
|
1581
|
+
this.mCurrent = Math.min(this.max, this.mCurrent + value);
|
|
1716
1582
|
await this.save();
|
|
1717
|
-
return asset;
|
|
1718
1583
|
}
|
|
1719
|
-
async
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
await this.
|
|
1723
|
-
|
|
1584
|
+
async cancel() {
|
|
1585
|
+
if (!this.parent)
|
|
1586
|
+
return null;
|
|
1587
|
+
await this.parent.cancel();
|
|
1588
|
+
}
|
|
1589
|
+
async save() {
|
|
1590
|
+
const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
|
|
1591
|
+
const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
|
|
1592
|
+
const current = this.parent.current;
|
|
1593
|
+
if (newProgress <= current)
|
|
1594
|
+
return null;
|
|
1595
|
+
await this.parent.advance(newProgress);
|
|
1596
|
+
}
|
|
1597
|
+
async load() {
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1600
|
+
toJSON() {
|
|
1601
|
+
return this.parent.toJSON();
|
|
1724
1602
|
}
|
|
1725
1603
|
}
|
|
1726
1604
|
|
|
1605
|
+
let Progresses = class Progresses {
|
|
1606
|
+
constructor(connector, jobMan) {
|
|
1607
|
+
this.connector = connector;
|
|
1608
|
+
this.jobMan = jobMan;
|
|
1609
|
+
this.collection = connector.database.collection("progresses");
|
|
1610
|
+
this.progresses = {};
|
|
1611
|
+
this.jobMan.on("progress-changed", progress => {
|
|
1612
|
+
const id = progress.id;
|
|
1613
|
+
this.progresses[id] = new Progress(new ObjectId$1(id), progress, this.collection);
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
async waitToFinish(id) {
|
|
1617
|
+
return Promise.race([
|
|
1618
|
+
this.waitForProgress(id, async () => {
|
|
1619
|
+
let progress = this.progresses[id];
|
|
1620
|
+
if (!progress || progress.percent < 100) {
|
|
1621
|
+
progress = await this.get(id);
|
|
1622
|
+
}
|
|
1623
|
+
if (!progress) {
|
|
1624
|
+
throw new Error(`Progress does not exists with id: ${id}`);
|
|
1625
|
+
}
|
|
1626
|
+
return progress;
|
|
1627
|
+
}, 500),
|
|
1628
|
+
this.waitForProgress(id, async () => {
|
|
1629
|
+
return this.progresses[id] || null;
|
|
1630
|
+
}, 25)
|
|
1631
|
+
]);
|
|
1632
|
+
}
|
|
1633
|
+
async get(id) {
|
|
1634
|
+
return !id ? null : this.find({ _id: new ObjectId$1(id) });
|
|
1635
|
+
}
|
|
1636
|
+
async find(where) {
|
|
1637
|
+
const data = await this.collection.findOne(where);
|
|
1638
|
+
return !data ? null : new Progress(data._id, data, this.collection);
|
|
1639
|
+
}
|
|
1640
|
+
async create(max = 100) {
|
|
1641
|
+
if (isNaN(max) || max <= 0) {
|
|
1642
|
+
throw new Error(`Max progress value must be bigger than zero`);
|
|
1643
|
+
}
|
|
1644
|
+
const data = {
|
|
1645
|
+
current: 0,
|
|
1646
|
+
max: max,
|
|
1647
|
+
message: "",
|
|
1648
|
+
error: "",
|
|
1649
|
+
canceled: false
|
|
1650
|
+
};
|
|
1651
|
+
const res = await this.collection.insertOne(data);
|
|
1652
|
+
return new Progress(res.insertedId, data, this.collection);
|
|
1653
|
+
}
|
|
1654
|
+
async remove(id) {
|
|
1655
|
+
await this.collection.deleteOne({ _id: new ObjectId$1(id) });
|
|
1656
|
+
return id;
|
|
1657
|
+
}
|
|
1658
|
+
async waitForProgress(id, cb, delay) {
|
|
1659
|
+
let isFinished = false;
|
|
1660
|
+
let progress = null;
|
|
1661
|
+
let waitTime = 0;
|
|
1662
|
+
while (!isFinished) {
|
|
1663
|
+
progress = await cb();
|
|
1664
|
+
waitTime += delay;
|
|
1665
|
+
if (progress) {
|
|
1666
|
+
if (progress.error) {
|
|
1667
|
+
throw new Error(progress.error);
|
|
1668
|
+
}
|
|
1669
|
+
isFinished = progress.percent >= 100;
|
|
1670
|
+
}
|
|
1671
|
+
if (!isFinished) {
|
|
1672
|
+
if (waitTime >= this.jobMan.maxTimeout) {
|
|
1673
|
+
throw new Error(`Progress with id: ${id} probably never will be finished!`);
|
|
1674
|
+
}
|
|
1675
|
+
await promiseTimeout(delay);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return progress;
|
|
1679
|
+
}
|
|
1680
|
+
};
|
|
1681
|
+
Progresses = __decorate([
|
|
1682
|
+
singleton(),
|
|
1683
|
+
__metadata("design:paramtypes", [MongoConnector, JobManager])
|
|
1684
|
+
], Progresses);
|
|
1685
|
+
|
|
1727
1686
|
let LazyAssets = class LazyAssets {
|
|
1728
1687
|
constructor(connector, assets, progresses, logger, jobMan) {
|
|
1729
1688
|
this.connector = connector;
|
|
@@ -1764,94 +1723,114 @@ let LazyAssets = class LazyAssets {
|
|
|
1764
1723
|
};
|
|
1765
1724
|
LazyAssets = __decorate([
|
|
1766
1725
|
injectable(),
|
|
1767
|
-
scoped(Lifecycle.ContainerScoped)
|
|
1726
|
+
scoped(Lifecycle.ContainerScoped),
|
|
1727
|
+
__metadata("design:paramtypes", [MongoConnector,
|
|
1728
|
+
Assets,
|
|
1729
|
+
Progresses,
|
|
1730
|
+
Logger,
|
|
1731
|
+
JobManager])
|
|
1768
1732
|
], LazyAssets);
|
|
1769
1733
|
|
|
1770
|
-
let
|
|
1771
|
-
constructor(
|
|
1772
|
-
this.
|
|
1773
|
-
this.
|
|
1774
|
-
this.ignoredTags = this.config.resolve("ignoredLogTags");
|
|
1734
|
+
let AssetResolver = class AssetResolver {
|
|
1735
|
+
constructor(assets, lazyAssets) {
|
|
1736
|
+
this.assets = assets;
|
|
1737
|
+
this.lazyAssets = lazyAssets;
|
|
1775
1738
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1739
|
+
async resolve(id, lazy = false) {
|
|
1740
|
+
let asset = null;
|
|
1741
|
+
if (lazy) {
|
|
1742
|
+
const lazyAsset = await this.lazyAssets.read(id);
|
|
1743
|
+
if (!lazyAsset)
|
|
1744
|
+
return null;
|
|
1745
|
+
return lazyAsset.loadAsset();
|
|
1746
|
+
}
|
|
1747
|
+
asset = await this.assets.read(id);
|
|
1748
|
+
if (!asset) {
|
|
1749
|
+
const lazyAsset = await this.lazyAssets.read(id);
|
|
1750
|
+
if (!lazyAsset)
|
|
1751
|
+
return null;
|
|
1752
|
+
return lazyAsset.loadAsset();
|
|
1781
1753
|
}
|
|
1754
|
+
return asset;
|
|
1782
1755
|
}
|
|
1783
1756
|
};
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1757
|
+
AssetResolver = __decorate([
|
|
1758
|
+
injectable(),
|
|
1759
|
+
scoped(Lifecycle.ContainerScoped),
|
|
1760
|
+
__metadata("design:paramtypes", [Assets, LazyAssets])
|
|
1761
|
+
], AssetResolver);
|
|
1787
1762
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
this.
|
|
1792
|
-
this.
|
|
1793
|
-
|
|
1794
|
-
port: this.config.resolve("smtpPort"),
|
|
1795
|
-
auth: {
|
|
1796
|
-
user: this.config.resolve("smtpUser"),
|
|
1797
|
-
pass: this.config.resolve("smtpPassword"),
|
|
1798
|
-
}
|
|
1799
|
-
});
|
|
1763
|
+
const express = express_;
|
|
1764
|
+
let BackendProvider = class BackendProvider {
|
|
1765
|
+
constructor() {
|
|
1766
|
+
this.express = express();
|
|
1767
|
+
this.express.set("trust proxy", true);
|
|
1768
|
+
this.server = createServer(this.express);
|
|
1800
1769
|
}
|
|
1801
|
-
get
|
|
1802
|
-
|
|
1770
|
+
get io() {
|
|
1771
|
+
this.ioServer = this.ioServer || new Server(this.server, { path: "/socket" });
|
|
1772
|
+
return this.ioServer;
|
|
1803
1773
|
}
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1774
|
+
};
|
|
1775
|
+
BackendProvider = __decorate([
|
|
1776
|
+
singleton(),
|
|
1777
|
+
__metadata("design:paramtypes", [])
|
|
1778
|
+
], BackendProvider);
|
|
1779
|
+
|
|
1780
|
+
let CacheProcessor = class CacheProcessor {
|
|
1781
|
+
async serialize(data) {
|
|
1782
|
+
return data;
|
|
1783
|
+
}
|
|
1784
|
+
async deserialize(data) {
|
|
1785
|
+
return data;
|
|
1814
1786
|
}
|
|
1815
1787
|
};
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1788
|
+
CacheProcessor = __decorate([
|
|
1789
|
+
injectable(),
|
|
1790
|
+
scoped(Lifecycle.ContainerScoped)
|
|
1791
|
+
], CacheProcessor);
|
|
1819
1792
|
|
|
1820
|
-
let
|
|
1821
|
-
constructor(
|
|
1822
|
-
this.
|
|
1823
|
-
this.
|
|
1793
|
+
let Cache = class Cache {
|
|
1794
|
+
constructor(connector, config, cacheProcessor) {
|
|
1795
|
+
this.connector = connector;
|
|
1796
|
+
this.config = config;
|
|
1797
|
+
this.cacheProcessor = cacheProcessor;
|
|
1798
|
+
}
|
|
1799
|
+
async prepare() {
|
|
1800
|
+
if (this.collection)
|
|
1801
|
+
return;
|
|
1802
|
+
if (!this.connector.database) {
|
|
1803
|
+
throw new Error(`You can't use cache without mongo connection!`);
|
|
1804
|
+
}
|
|
1805
|
+
this.collection = this.connector.database.collection(this.config.resolve("cacheCollection"));
|
|
1806
|
+
await this.collection.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1824
1807
|
}
|
|
1825
1808
|
async set(key, value, ttl, expirationTimestamp = null, tags = {}) {
|
|
1826
|
-
|
|
1827
|
-
const
|
|
1828
|
-
this.cacheMap.set(key, {
|
|
1809
|
+
await this.prepare();
|
|
1810
|
+
const item = {
|
|
1829
1811
|
_id: key,
|
|
1830
|
-
data: value,
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1812
|
+
data: await this.cacheProcessor.serialize(value),
|
|
1813
|
+
tags: await this.cacheProcessor.serialize(tags),
|
|
1814
|
+
expirationTimestamp,
|
|
1815
|
+
};
|
|
1816
|
+
if (ttl) {
|
|
1817
|
+
const now = Math.round(new Date().getTime() / 1000);
|
|
1818
|
+
item.expiresAt = now + ttl;
|
|
1819
|
+
}
|
|
1820
|
+
await this.collection.updateOne({ _id: key }, { $set: item }, { upsert: true });
|
|
1821
|
+
return value;
|
|
1835
1822
|
}
|
|
1836
1823
|
async get(key) {
|
|
1837
|
-
|
|
1824
|
+
await this.prepare();
|
|
1825
|
+
let item = await this.collection.findOne({ _id: key });
|
|
1838
1826
|
const now = Math.round(new Date().getTime() / 1000);
|
|
1839
|
-
let expTimestamp = 3600;
|
|
1840
1827
|
if (item && item.expiresAt && item.expiresAt < now) {
|
|
1841
|
-
expTimestamp = item.expirationTimestamp;
|
|
1842
1828
|
item = null;
|
|
1843
1829
|
}
|
|
1844
1830
|
if (!item) {
|
|
1845
|
-
|
|
1846
|
-
this.cacheMap.set(key, {
|
|
1847
|
-
_id: key,
|
|
1848
|
-
data: value,
|
|
1849
|
-
expirationTimestamp: expTimestamp,
|
|
1850
|
-
expiresAt: now + expTimestamp,
|
|
1851
|
-
});
|
|
1852
|
-
return value;
|
|
1831
|
+
throw new Error(`Cache probably doesn't exists with key: ${key}`);
|
|
1853
1832
|
}
|
|
1854
|
-
return item.data;
|
|
1833
|
+
return await this.cacheProcessor.deserialize(item.data);
|
|
1855
1834
|
}
|
|
1856
1835
|
async getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
|
|
1857
1836
|
try {
|
|
@@ -1862,446 +1841,345 @@ let MemoryCache = class MemoryCache {
|
|
|
1862
1841
|
}
|
|
1863
1842
|
}
|
|
1864
1843
|
async delete(key) {
|
|
1865
|
-
this.
|
|
1866
|
-
await this.
|
|
1844
|
+
await this.prepare();
|
|
1845
|
+
await this.collection.deleteOne({ _id: key });
|
|
1867
1846
|
}
|
|
1868
1847
|
};
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
],
|
|
1848
|
+
Cache = __decorate([
|
|
1849
|
+
singleton(),
|
|
1850
|
+
__metadata("design:paramtypes", [MongoConnector, Configuration, CacheProcessor])
|
|
1851
|
+
], Cache);
|
|
1873
1852
|
|
|
1874
|
-
let
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
this.conn = null;
|
|
1878
|
-
this.db = null;
|
|
1879
|
-
this.fsBucket = null;
|
|
1880
|
-
}
|
|
1881
|
-
get connection() {
|
|
1882
|
-
return this.conn;
|
|
1883
|
-
}
|
|
1884
|
-
get database() {
|
|
1885
|
-
return this.db;
|
|
1886
|
-
}
|
|
1887
|
-
get bucket() {
|
|
1888
|
-
return this.fsBucket;
|
|
1889
|
-
}
|
|
1890
|
-
async connect() {
|
|
1891
|
-
if (this.db)
|
|
1892
|
-
return this.db;
|
|
1893
|
-
this.conn = (await connect(this.configuration.resolve("mongoUri"), {
|
|
1894
|
-
dbName: this.configuration.resolve("mongoDb"),
|
|
1895
|
-
user: this.configuration.resolve("mongoUser"),
|
|
1896
|
-
pass: this.configuration.resolve("mongoPassword")
|
|
1897
|
-
})).connection;
|
|
1898
|
-
this.db = this.conn.db;
|
|
1899
|
-
this.fsBucket = new GridFSBucket(this.db, { bucketName: "assets" });
|
|
1853
|
+
let EndpointProvider = class EndpointProvider {
|
|
1854
|
+
async configure(app) {
|
|
1855
|
+
console.log(`Express app is mounted to: ${app.mountpath}`);
|
|
1900
1856
|
}
|
|
1901
1857
|
};
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1858
|
+
EndpointProvider = __decorate([
|
|
1859
|
+
injectable(),
|
|
1860
|
+
scoped(Lifecycle.ContainerScoped)
|
|
1861
|
+
], EndpointProvider);
|
|
1905
1862
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
try {
|
|
1910
|
-
const id = new ObjectId$1(v);
|
|
1911
|
-
return id instanceof ObjectId$1;
|
|
1912
|
-
}
|
|
1913
|
-
catch (e) {
|
|
1914
|
-
return false;
|
|
1915
|
-
}
|
|
1916
|
-
});
|
|
1917
|
-
}
|
|
1918
|
-
if (null === value)
|
|
1919
|
-
return true;
|
|
1920
|
-
try {
|
|
1921
|
-
const id = new ObjectId$1(value);
|
|
1922
|
-
return id instanceof ObjectId$1;
|
|
1923
|
-
}
|
|
1924
|
-
catch (e) {
|
|
1925
|
-
return false;
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
let IsFile = class IsFile {
|
|
1929
|
-
validate(value, validationArguments) {
|
|
1930
|
-
const [multi] = (validationArguments.constraints || []);
|
|
1931
|
-
return checkValue(multi, value);
|
|
1863
|
+
let Fixtures = class Fixtures {
|
|
1864
|
+
constructor(fixtures) {
|
|
1865
|
+
this.fixtures = fixtures;
|
|
1932
1866
|
}
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1867
|
+
async load(output) {
|
|
1868
|
+
if (!this.fixtures)
|
|
1869
|
+
return;
|
|
1870
|
+
output = output || {
|
|
1871
|
+
write: console.log,
|
|
1872
|
+
writeln: t => console.log(t + "\n")
|
|
1873
|
+
};
|
|
1874
|
+
for (let fixture of this.fixtures) {
|
|
1875
|
+
await fixture.load(output);
|
|
1876
|
+
}
|
|
1941
1877
|
}
|
|
1942
1878
|
};
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1879
|
+
Fixtures = __decorate([
|
|
1880
|
+
injectable(),
|
|
1881
|
+
scoped(Lifecycle.ContainerScoped),
|
|
1882
|
+
__param(0, injectAll(FIXTURE)),
|
|
1883
|
+
__metadata("design:paramtypes", [Array])
|
|
1884
|
+
], Fixtures);
|
|
1946
1885
|
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
}
|
|
1958
|
-
get apiDocsStr() {
|
|
1959
|
-
if (!this.docsStr)
|
|
1960
|
-
this.docsStr = JSON.stringify(this.apiDocs);
|
|
1961
|
-
return this.docsStr;
|
|
1886
|
+
const sharp$1 = sharp_;
|
|
1887
|
+
const bigSize = 1500;
|
|
1888
|
+
const thumbSize = 250;
|
|
1889
|
+
class GalleryImage {
|
|
1890
|
+
constructor(folder, size, handler) {
|
|
1891
|
+
this.folder = folder;
|
|
1892
|
+
this.handler = handler;
|
|
1893
|
+
this.thumb = v4();
|
|
1894
|
+
this.big = v4();
|
|
1895
|
+
this.targetSize = !size ? { width: thumbSize, height: thumbSize } : size;
|
|
1962
1896
|
}
|
|
1963
|
-
async
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
.replace("#/components/schemas/", "")
|
|
1968
|
-
.replace("#/definitions/", "");
|
|
1969
|
-
return this.schemaToExample(schemas[schema], req);
|
|
1970
|
-
}
|
|
1971
|
-
let schema = src;
|
|
1972
|
-
if (schema.oneOf) {
|
|
1973
|
-
schema = Object.assign({}, schema, schema.oneOf[0]);
|
|
1974
|
-
}
|
|
1975
|
-
if (schema.type === "object") {
|
|
1976
|
-
const result = {};
|
|
1977
|
-
await Promise.all(Object.keys(schema.properties).map(async (key) => {
|
|
1978
|
-
result[key] = await this.schemaToExample(schema.properties[key], req);
|
|
1979
|
-
}));
|
|
1980
|
-
return result;
|
|
1981
|
-
}
|
|
1982
|
-
if (schema.type === "array") {
|
|
1983
|
-
return [await this.schemaToExample(schema.items, req)];
|
|
1984
|
-
}
|
|
1985
|
-
if (schema.type === "string") {
|
|
1986
|
-
if (isDefined(schema.default)) {
|
|
1987
|
-
if (isFunction(schema.default)) {
|
|
1988
|
-
return schema.default(this.container);
|
|
1989
|
-
}
|
|
1990
|
-
return schema.default;
|
|
1991
|
-
}
|
|
1992
|
-
if (schema.format == "date") {
|
|
1993
|
-
return new Date().toISOString().substr(0, 10);
|
|
1994
|
-
}
|
|
1995
|
-
if (schema.format == "date-time") {
|
|
1996
|
-
return new Date().toISOString();
|
|
1997
|
-
}
|
|
1998
|
-
if (schema.enum) {
|
|
1999
|
-
return schema.enum[0];
|
|
2000
|
-
}
|
|
2001
|
-
return "string";
|
|
2002
|
-
}
|
|
2003
|
-
if (schema.type === "number") {
|
|
2004
|
-
return schema.default ?? 0;
|
|
2005
|
-
}
|
|
2006
|
-
else if (schema.type === "boolean") {
|
|
2007
|
-
return schema.default ?? false;
|
|
2008
|
-
}
|
|
2009
|
-
else {
|
|
2010
|
-
return schema.default ?? null;
|
|
1897
|
+
async serve(id) {
|
|
1898
|
+
const isThumb = id == this.thumb;
|
|
1899
|
+
if (await this.handler.hasResult(isThumb)) {
|
|
1900
|
+
return this.handler.serveResult(isThumb);
|
|
2011
1901
|
}
|
|
1902
|
+
const original = sharp$1(await this.handler.getOriginal()).rotate();
|
|
1903
|
+
const meta = await original.metadata();
|
|
1904
|
+
const ratio = meta.width / meta.height;
|
|
1905
|
+
const sizeRatio = isThumb ? this.targetSize.width / this.targetSize.height : 1;
|
|
1906
|
+
const size = isThumb ? Math.max(this.targetSize.width, this.targetSize.height) : bigSize;
|
|
1907
|
+
const targetHeight = ratio > sizeRatio ? size : Math.round(size / ratio);
|
|
1908
|
+
const targetWidth = Math.round(targetHeight * ratio);
|
|
1909
|
+
const resized = original.resize(targetWidth, targetHeight);
|
|
1910
|
+
const buffer = await (isThumb ? resized.extract({
|
|
1911
|
+
left: Math.floor((targetWidth - this.targetSize.width) / 2),
|
|
1912
|
+
top: Math.floor((targetHeight - this.targetSize.height) / 2),
|
|
1913
|
+
width: this.targetSize.width,
|
|
1914
|
+
height: this.targetSize.height
|
|
1915
|
+
}).toBuffer() : resized.toBuffer());
|
|
1916
|
+
await this.handler.writeResult(isThumb, buffer);
|
|
1917
|
+
return this.handler.serveResult(isThumb);
|
|
2012
1918
|
}
|
|
2013
|
-
|
|
2014
|
-
const storage = getMetadataArgsStorage();
|
|
2015
|
-
const docs = routingControllersToSpec(storage);
|
|
2016
|
-
docs.basePath = "/api/";
|
|
2017
|
-
docs.definitions = validationMetadatasToSchemas({
|
|
2018
|
-
additionalConverters: {
|
|
2019
|
-
[ValidationTypes.CUSTOM_VALIDATION]: (meta, options) => {
|
|
2020
|
-
const res = isFunction(this.customValidation) ? this.customValidation(meta, options) : this.customValidation;
|
|
2021
|
-
if (isObject(res))
|
|
2022
|
-
return res;
|
|
2023
|
-
const constraints = meta.constraints || [];
|
|
2024
|
-
if (meta.constraintCls === IsFile) {
|
|
2025
|
-
return {
|
|
2026
|
-
multi: constraints[0] || false,
|
|
2027
|
-
type: "file"
|
|
2028
|
-
};
|
|
2029
|
-
}
|
|
2030
|
-
if (meta.constraintCls === IsObjectId) {
|
|
2031
|
-
return {
|
|
2032
|
-
endpoint: constraints[0] || false,
|
|
2033
|
-
multi: constraints[1] || false,
|
|
2034
|
-
type: "list"
|
|
2035
|
-
};
|
|
2036
|
-
}
|
|
2037
|
-
return null;
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
});
|
|
2041
|
-
docs.components.schemas = docs.definitions;
|
|
2042
|
-
return docs;
|
|
2043
|
-
}
|
|
2044
|
-
};
|
|
2045
|
-
OpenApi = __decorate([
|
|
2046
|
-
singleton(),
|
|
2047
|
-
__param(0, inject(DI_CONTAINER)),
|
|
2048
|
-
__param(1, inject(OPENAPI_VALIDATION))
|
|
2049
|
-
], OpenApi);
|
|
1919
|
+
}
|
|
2050
1920
|
|
|
2051
|
-
|
|
2052
|
-
constructor(
|
|
2053
|
-
|
|
1921
|
+
let GalleryCache = class GalleryCache {
|
|
1922
|
+
constructor() {
|
|
1923
|
+
this.imgCache = {};
|
|
2054
1924
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
1925
|
+
put(img) {
|
|
1926
|
+
this.imgCache[img.thumb] = img;
|
|
1927
|
+
this.imgCache[img.big] = img;
|
|
2057
1928
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
1929
|
+
serve(id) {
|
|
1930
|
+
const img = this.imgCache[id];
|
|
1931
|
+
return !img ? null : img.serve(id);
|
|
2060
1932
|
}
|
|
2061
|
-
|
|
2062
|
-
|
|
1933
|
+
create(folder, targetSize, handler) {
|
|
1934
|
+
const image = new GalleryImage(folder, targetSize, handler);
|
|
1935
|
+
this.put(image);
|
|
1936
|
+
return image;
|
|
2063
1937
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
1938
|
+
};
|
|
1939
|
+
GalleryCache = __decorate([
|
|
1940
|
+
injectable(),
|
|
1941
|
+
scoped(Lifecycle.ContainerScoped),
|
|
1942
|
+
__metadata("design:paramtypes", [])
|
|
1943
|
+
], GalleryCache);
|
|
1944
|
+
|
|
1945
|
+
const sharp = sharp_;
|
|
1946
|
+
let Gallery = class Gallery {
|
|
1947
|
+
constructor(config, galleryCache) {
|
|
1948
|
+
this.config = config;
|
|
1949
|
+
this.galleryCache = galleryCache;
|
|
1950
|
+
this.cache = {};
|
|
1951
|
+
this.dir = this.config.resolve("galleryDir");
|
|
1952
|
+
this.output = join(this.config.resolve("cacheDir"), "gallery");
|
|
2066
1953
|
}
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
return this;
|
|
2079
|
-
}
|
|
2080
|
-
async createSubProgress(progressValue, max, message) {
|
|
2081
|
-
if (max <= 0 && progressValue > 0) {
|
|
2082
|
-
await this.advance(progressValue);
|
|
2083
|
-
}
|
|
2084
|
-
if (message !== null) {
|
|
2085
|
-
this.data.message = message;
|
|
2086
|
-
await this.save();
|
|
2087
|
-
}
|
|
2088
|
-
return new SubProgress(this, this.current, progressValue, Math.max(max, 1));
|
|
2089
|
-
}
|
|
2090
|
-
async setMax(max) {
|
|
2091
|
-
if (isNaN(max) || max <= 0) {
|
|
2092
|
-
throw "Max progress value must be bigger than zero";
|
|
2093
|
-
}
|
|
2094
|
-
this.data.max = max;
|
|
2095
|
-
await this.save();
|
|
2096
|
-
}
|
|
2097
|
-
async setMessage(message) {
|
|
2098
|
-
this.data.message = message;
|
|
2099
|
-
await this.save();
|
|
2100
|
-
}
|
|
2101
|
-
async setError(error) {
|
|
2102
|
-
this.data.error = error;
|
|
2103
|
-
await this.save();
|
|
2104
|
-
}
|
|
2105
|
-
async advance(value = 1) {
|
|
2106
|
-
if (isNaN(value) || value <= 0) {
|
|
2107
|
-
throw new Error(`Advance value must be bigger than zero: ${this.id}`);
|
|
2108
|
-
}
|
|
2109
|
-
await this.load();
|
|
2110
|
-
if (this.deleted || this.canceled) {
|
|
2111
|
-
const status = this.deleted ? "deleted" : "canceled";
|
|
2112
|
-
throw new Error(`Can't advance ${status} progress: ${this.id}`);
|
|
2113
|
-
}
|
|
2114
|
-
this.data.current = Math.min(this.max, this.current + value);
|
|
2115
|
-
await this.save();
|
|
2116
|
-
}
|
|
2117
|
-
async cancel() {
|
|
2118
|
-
this.data.canceled = true;
|
|
2119
|
-
await this.save();
|
|
2120
|
-
}
|
|
2121
|
-
save() {
|
|
2122
|
-
if (this.messageBridge) {
|
|
2123
|
-
this.messageBridge.sendMessage(`progress-changed`, this.toJSON());
|
|
2124
|
-
}
|
|
2125
|
-
return super.save();
|
|
2126
|
-
}
|
|
2127
|
-
}
|
|
2128
|
-
class SubProgress {
|
|
2129
|
-
constructor(parent, progressFrom, progressValue, mMax = 100) {
|
|
2130
|
-
this.parent = parent;
|
|
2131
|
-
this.progressFrom = progressFrom;
|
|
2132
|
-
this.progressValue = progressValue;
|
|
2133
|
-
this.mMax = mMax;
|
|
2134
|
-
if (progressFrom < 0) {
|
|
2135
|
-
throw "Progress from must be bigger than or zero";
|
|
2136
|
-
}
|
|
2137
|
-
if (progressValue <= 0) {
|
|
2138
|
-
throw "Progress value must be bigger than zero";
|
|
2139
|
-
}
|
|
2140
|
-
this.mCurrent = 0;
|
|
2141
|
-
}
|
|
2142
|
-
get id() {
|
|
2143
|
-
return this.parent.id;
|
|
2144
|
-
}
|
|
2145
|
-
get current() {
|
|
2146
|
-
return this.mCurrent;
|
|
2147
|
-
}
|
|
2148
|
-
get max() {
|
|
2149
|
-
return this.mMax;
|
|
2150
|
-
}
|
|
2151
|
-
get message() {
|
|
2152
|
-
return this.parent.message;
|
|
2153
|
-
}
|
|
2154
|
-
get error() {
|
|
2155
|
-
return this.parent.error;
|
|
2156
|
-
}
|
|
2157
|
-
get percent() {
|
|
2158
|
-
return this.parent.percent;
|
|
2159
|
-
}
|
|
2160
|
-
get remaining() {
|
|
2161
|
-
return this.max - this.mCurrent;
|
|
2162
|
-
}
|
|
2163
|
-
get canceled() {
|
|
2164
|
-
return !this.parent || this.parent.canceled;
|
|
1954
|
+
async getFolder(folder, size = null) {
|
|
1955
|
+
this.cache[folder] = this.cache[folder] || new Promise(resolve => {
|
|
1956
|
+
lstat(join(this.dir, folder), (err, stats) => {
|
|
1957
|
+
if (err || !stats.isDirectory()) {
|
|
1958
|
+
resolve([]);
|
|
1959
|
+
return;
|
|
1960
|
+
}
|
|
1961
|
+
this.readRecursive(folder, "", size).then(resolve, () => resolve([]));
|
|
1962
|
+
});
|
|
1963
|
+
});
|
|
1964
|
+
return this.cache[folder];
|
|
2165
1965
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
1966
|
+
readRecursive(path, folder, size) {
|
|
1967
|
+
return new Promise(resolve => {
|
|
1968
|
+
readdir(join(this.dir, path), (err, files) => {
|
|
1969
|
+
if (err) {
|
|
1970
|
+
resolve([]);
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
const promises = files.map(file => {
|
|
1974
|
+
return new Promise(async (resolve) => {
|
|
1975
|
+
const filePath = join(path, file);
|
|
1976
|
+
const absoluteFilePath = join(this.dir, filePath);
|
|
1977
|
+
lstat(absoluteFilePath, (err, stats) => {
|
|
1978
|
+
if (err) {
|
|
1979
|
+
resolve([]);
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
if (stats.isDirectory()) {
|
|
1983
|
+
this.readRecursive(filePath, join(folder, file), size).then(resolve);
|
|
1984
|
+
return;
|
|
1985
|
+
}
|
|
1986
|
+
const sharpImg = sharp(absoluteFilePath);
|
|
1987
|
+
sharpImg.rotate().metadata().then(() => {
|
|
1988
|
+
const getResultPath = (isThumb) => {
|
|
1989
|
+
return join(this.output, filePath.replace(/.([a-z|A-Z]+)$/gi, function (ext) {
|
|
1990
|
+
const suffix = isThumb ? 'thumb' : 'big';
|
|
1991
|
+
return `-${suffix}${ext}`;
|
|
1992
|
+
}));
|
|
1993
|
+
};
|
|
1994
|
+
resolve([this.galleryCache.create(folder, size, {
|
|
1995
|
+
getOriginal: () => {
|
|
1996
|
+
return new Promise((res, rej) => {
|
|
1997
|
+
readFile$1(absoluteFilePath, (err, data) => {
|
|
1998
|
+
if (err) {
|
|
1999
|
+
rej(err);
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
res(data);
|
|
2003
|
+
});
|
|
2004
|
+
});
|
|
2005
|
+
},
|
|
2006
|
+
writeResult: (isThumb, buffer) => {
|
|
2007
|
+
return new Promise(async (res, rej) => {
|
|
2008
|
+
const resultPath = getResultPath(isThumb);
|
|
2009
|
+
await mkdirRecursive(dirname(resultPath));
|
|
2010
|
+
writeFile$1(resultPath, buffer, err => {
|
|
2011
|
+
if (err) {
|
|
2012
|
+
rej(err);
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
res();
|
|
2016
|
+
});
|
|
2017
|
+
});
|
|
2018
|
+
},
|
|
2019
|
+
hasResult: (isThumb) => {
|
|
2020
|
+
return new Promise(res => {
|
|
2021
|
+
access(getResultPath(isThumb), constants.R_OK, err => {
|
|
2022
|
+
res(!err);
|
|
2023
|
+
});
|
|
2024
|
+
});
|
|
2025
|
+
},
|
|
2026
|
+
serveResult: (isThumb) => {
|
|
2027
|
+
return new Promise((res, rej) => {
|
|
2028
|
+
readFile$1(getResultPath(isThumb), (err, data) => {
|
|
2029
|
+
if (err) {
|
|
2030
|
+
rej(err);
|
|
2031
|
+
return;
|
|
2032
|
+
}
|
|
2033
|
+
res(data);
|
|
2034
|
+
});
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
})]);
|
|
2038
|
+
}, () => resolve([]));
|
|
2039
|
+
});
|
|
2040
|
+
});
|
|
2041
|
+
});
|
|
2042
|
+
Promise.all(promises).then(folders => {
|
|
2043
|
+
resolve([].concat.apply([], folders));
|
|
2044
|
+
});
|
|
2045
|
+
});
|
|
2046
|
+
});
|
|
2171
2047
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2048
|
+
};
|
|
2049
|
+
Gallery = __decorate([
|
|
2050
|
+
injectable(),
|
|
2051
|
+
scoped(Lifecycle.ContainerScoped),
|
|
2052
|
+
__metadata("design:paramtypes", [Configuration, GalleryCache])
|
|
2053
|
+
], Gallery);
|
|
2054
|
+
|
|
2055
|
+
let IdGenerator = class IdGenerator {
|
|
2056
|
+
constructor(config) {
|
|
2057
|
+
this.config = config;
|
|
2058
|
+
this.prefix = config.resolve("idPrefix");
|
|
2059
|
+
this.separator = config.resolve("idSeparator");
|
|
2060
|
+
this.chars = config.resolve("idChars");
|
|
2061
|
+
this.parts = config.resolve("idParts");
|
|
2180
2062
|
}
|
|
2181
|
-
async
|
|
2182
|
-
|
|
2183
|
-
|
|
2063
|
+
async generate(checkCb) {
|
|
2064
|
+
let id = null;
|
|
2065
|
+
let tries = 0;
|
|
2066
|
+
let notGood = true;
|
|
2067
|
+
while (notGood && tries < 5) {
|
|
2068
|
+
id = this.generateId();
|
|
2069
|
+
notGood = await checkCb(id);
|
|
2070
|
+
tries++;
|
|
2184
2071
|
}
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
}
|
|
2188
|
-
async setMessage(message) {
|
|
2189
|
-
if (!this.parent)
|
|
2190
|
-
return null;
|
|
2191
|
-
await this.parent.setMessage(message);
|
|
2192
|
-
}
|
|
2193
|
-
async setError(error) {
|
|
2194
|
-
if (!this.parent)
|
|
2195
|
-
return null;
|
|
2196
|
-
await this.parent.setError(error);
|
|
2197
|
-
}
|
|
2198
|
-
async advance(value = 1) {
|
|
2199
|
-
if (isNaN(value) || value <= 0) {
|
|
2200
|
-
throw "Advance value must be bigger than zero";
|
|
2072
|
+
if (notGood) {
|
|
2073
|
+
throw `Couldn't generate an unique id..`;
|
|
2201
2074
|
}
|
|
2202
|
-
|
|
2203
|
-
await this.save();
|
|
2204
|
-
}
|
|
2205
|
-
async cancel() {
|
|
2206
|
-
if (!this.parent)
|
|
2207
|
-
return null;
|
|
2208
|
-
await this.parent.cancel();
|
|
2209
|
-
}
|
|
2210
|
-
async save() {
|
|
2211
|
-
const ratio = this.max > 0 ? this.mCurrent / this.max : 0;
|
|
2212
|
-
const newProgress = this.progressFrom + Math.round(this.progressValue * ratio);
|
|
2213
|
-
const current = this.parent.current;
|
|
2214
|
-
if (newProgress <= current)
|
|
2215
|
-
return null;
|
|
2216
|
-
await this.parent.advance(newProgress);
|
|
2217
|
-
}
|
|
2218
|
-
async load() {
|
|
2219
|
-
return null;
|
|
2075
|
+
return id;
|
|
2220
2076
|
}
|
|
2221
|
-
|
|
2222
|
-
return this.
|
|
2077
|
+
generateId() {
|
|
2078
|
+
return this.prefix + this.parts.map(num => {
|
|
2079
|
+
let s = "";
|
|
2080
|
+
for (let i = 0; i < num; i++) {
|
|
2081
|
+
const ix = rand(0, this.chars.length - 1);
|
|
2082
|
+
s += this.chars[ix];
|
|
2083
|
+
}
|
|
2084
|
+
return s;
|
|
2085
|
+
}).join(this.separator);
|
|
2223
2086
|
}
|
|
2224
|
-
}
|
|
2087
|
+
};
|
|
2088
|
+
IdGenerator = __decorate([
|
|
2089
|
+
injectable(),
|
|
2090
|
+
scoped(Lifecycle.ContainerScoped),
|
|
2091
|
+
__metadata("design:paramtypes", [Configuration])
|
|
2092
|
+
], IdGenerator);
|
|
2225
2093
|
|
|
2226
|
-
let
|
|
2227
|
-
constructor(
|
|
2228
|
-
this.
|
|
2229
|
-
this.
|
|
2230
|
-
this.collection = connector.database.collection("progresses");
|
|
2231
|
-
this.progresses = {};
|
|
2232
|
-
this.jobMan.on("progress-changed", progress => {
|
|
2233
|
-
const id = progress.id;
|
|
2234
|
-
this.progresses[id] = new Progress(new ObjectId$1(id), progress, this.collection);
|
|
2235
|
-
});
|
|
2094
|
+
let TranslationProvider = class TranslationProvider {
|
|
2095
|
+
constructor(config, cache) {
|
|
2096
|
+
this.config = config;
|
|
2097
|
+
this.cache = cache;
|
|
2236
2098
|
}
|
|
2237
|
-
|
|
2238
|
-
return
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
if (
|
|
2245
|
-
|
|
2099
|
+
getDictionary(language) {
|
|
2100
|
+
return this.cache.getOrSet(`translations-${language}`, async () => {
|
|
2101
|
+
try {
|
|
2102
|
+
const url = this.config.resolve("translationsTemplate")
|
|
2103
|
+
.replace(`__lang__`, language)
|
|
2104
|
+
.replace(`[lang]`, language);
|
|
2105
|
+
const data = await axios.get(url).then(t => t.data);
|
|
2106
|
+
if (isObject(data[language])) {
|
|
2107
|
+
return data[language];
|
|
2246
2108
|
}
|
|
2247
|
-
return
|
|
2248
|
-
}
|
|
2249
|
-
|
|
2250
|
-
return
|
|
2251
|
-
|
|
2252
|
-
|
|
2109
|
+
return data;
|
|
2110
|
+
}
|
|
2111
|
+
catch (e) {
|
|
2112
|
+
return {
|
|
2113
|
+
message: `${e}`
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
}, 5 * 60);
|
|
2253
2117
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2118
|
+
};
|
|
2119
|
+
TranslationProvider = __decorate([
|
|
2120
|
+
singleton(),
|
|
2121
|
+
__metadata("design:paramtypes", [Configuration, Cache])
|
|
2122
|
+
], TranslationProvider);
|
|
2123
|
+
|
|
2124
|
+
let Translator = class Translator {
|
|
2125
|
+
constructor(translationProvider) {
|
|
2126
|
+
this.translationProvider = translationProvider;
|
|
2127
|
+
this.dictionaries = {};
|
|
2256
2128
|
}
|
|
2257
|
-
async
|
|
2258
|
-
|
|
2259
|
-
return
|
|
2129
|
+
async getDictionary(language) {
|
|
2130
|
+
this.dictionaries[language] = await this.translationProvider.getDictionary(language);
|
|
2131
|
+
return this.dictionaries[language];
|
|
2260
2132
|
}
|
|
2261
|
-
|
|
2262
|
-
if (
|
|
2263
|
-
throw new Error(`
|
|
2133
|
+
getTranslationSync(language, key, params) {
|
|
2134
|
+
if (!isString(key) || !key.length) {
|
|
2135
|
+
throw new Error(`Parameter "key" required`);
|
|
2264
2136
|
}
|
|
2265
|
-
const
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
message: "",
|
|
2269
|
-
error: "",
|
|
2270
|
-
canceled: false
|
|
2271
|
-
};
|
|
2272
|
-
const res = await this.collection.insertOne(data);
|
|
2273
|
-
return new Progress(res.insertedId, data, this.collection);
|
|
2274
|
-
}
|
|
2275
|
-
async remove(id) {
|
|
2276
|
-
await this.collection.deleteOne({ _id: new ObjectId$1(id) });
|
|
2277
|
-
return id;
|
|
2137
|
+
const dictionary = this.dictionaries[language];
|
|
2138
|
+
const translation = getValue(dictionary, key, key) || key;
|
|
2139
|
+
return this.interpolate(translation, params);
|
|
2278
2140
|
}
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
let waitTime = 0;
|
|
2283
|
-
while (!isFinished) {
|
|
2284
|
-
progress = await cb();
|
|
2285
|
-
waitTime += delay;
|
|
2286
|
-
if (progress) {
|
|
2287
|
-
if (progress.error) {
|
|
2288
|
-
throw new Error(progress.error);
|
|
2289
|
-
}
|
|
2290
|
-
isFinished = progress.percent >= 100;
|
|
2291
|
-
}
|
|
2292
|
-
if (!isFinished) {
|
|
2293
|
-
if (waitTime >= this.jobMan.maxTimeout) {
|
|
2294
|
-
throw new Error(`Progress with id: ${id} probably never will be finished!`);
|
|
2295
|
-
}
|
|
2296
|
-
await promiseTimeout(delay);
|
|
2297
|
-
}
|
|
2141
|
+
getTranslation(language, key, params) {
|
|
2142
|
+
if (!isString(key) || !key.length) {
|
|
2143
|
+
throw new Error(`Parameter "key" required`);
|
|
2298
2144
|
}
|
|
2299
|
-
return
|
|
2145
|
+
return this.getDictionary(language).then(dictionary => {
|
|
2146
|
+
const translation = getValue(dictionary, key, key) || key;
|
|
2147
|
+
return this.interpolate(translation, params);
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
getTranslations(language, ...keys) {
|
|
2151
|
+
return new Promise(resolve => {
|
|
2152
|
+
Promise.all(keys.map(key => this.getTranslation(language, key))).then(translations => {
|
|
2153
|
+
resolve(keys.reduce((result, key, i) => {
|
|
2154
|
+
result[key] = translations[i];
|
|
2155
|
+
return result;
|
|
2156
|
+
}, {}));
|
|
2157
|
+
});
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
interpolate(expr, params) {
|
|
2161
|
+
if (typeof expr === "string") {
|
|
2162
|
+
return this.interpolateString(expr, params);
|
|
2163
|
+
}
|
|
2164
|
+
if (typeof expr === "function") {
|
|
2165
|
+
return expr(params);
|
|
2166
|
+
}
|
|
2167
|
+
return expr;
|
|
2168
|
+
}
|
|
2169
|
+
interpolateString(expr, params) {
|
|
2170
|
+
if (!expr || !params)
|
|
2171
|
+
return expr;
|
|
2172
|
+
return expr.replace(/{{\s?([^{}\s]*)\s?}}/g, (substring, b) => {
|
|
2173
|
+
const r = getValue(params, b);
|
|
2174
|
+
return isDefined(r) ? r : substring;
|
|
2175
|
+
});
|
|
2300
2176
|
}
|
|
2301
2177
|
};
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2178
|
+
Translator = __decorate([
|
|
2179
|
+
injectable(),
|
|
2180
|
+
singleton(),
|
|
2181
|
+
__metadata("design:paramtypes", [TranslationProvider])
|
|
2182
|
+
], Translator);
|
|
2305
2183
|
|
|
2306
2184
|
let TemplateRenderer = class TemplateRenderer {
|
|
2307
2185
|
constructor(translator, config) {
|
|
@@ -2325,41 +2203,276 @@ let TemplateRenderer = class TemplateRenderer {
|
|
|
2325
2203
|
this.initPromise = this.initPromise || this.parseTemplates(this.config.resolve("templatesDir"), []);
|
|
2326
2204
|
return this.initPromise;
|
|
2327
2205
|
}
|
|
2328
|
-
async parseTemplates(dir, dirPath) {
|
|
2329
|
-
return new Promise(resolve => {
|
|
2330
|
-
readdir(dir, async (err, files) => {
|
|
2331
|
-
for (let file of files) {
|
|
2332
|
-
const path = join(dir, file);
|
|
2333
|
-
if (lstatSync(path).isDirectory()) {
|
|
2334
|
-
await this.parseTemplates(join(dir, file), dirPath.concat([file]));
|
|
2335
|
-
continue;
|
|
2206
|
+
async parseTemplates(dir, dirPath) {
|
|
2207
|
+
return new Promise(resolve => {
|
|
2208
|
+
readdir(dir, async (err, files) => {
|
|
2209
|
+
for (let file of files) {
|
|
2210
|
+
const path = join(dir, file);
|
|
2211
|
+
if (lstatSync(path).isDirectory()) {
|
|
2212
|
+
await this.parseTemplates(join(dir, file), dirPath.concat([file]));
|
|
2213
|
+
continue;
|
|
2214
|
+
}
|
|
2215
|
+
const parts = file.split(".");
|
|
2216
|
+
parts.pop();
|
|
2217
|
+
const name = parts.join(".");
|
|
2218
|
+
const fullName = dirPath.concat([name]).join("-");
|
|
2219
|
+
const content = readFileSync(path).toString("utf8");
|
|
2220
|
+
this.templates[fullName] = Handlebars.compile(content);
|
|
2221
|
+
Handlebars.registerPartial(fullName, content);
|
|
2222
|
+
}
|
|
2223
|
+
resolve();
|
|
2224
|
+
});
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
async render(template, language, context) {
|
|
2228
|
+
await this.init();
|
|
2229
|
+
await this.translator.getDictionary(language);
|
|
2230
|
+
if (!this.templates[template]) {
|
|
2231
|
+
return Promise.reject(`Template not found with name: ${template}`);
|
|
2232
|
+
}
|
|
2233
|
+
context = Object.assign({ language }, context || {});
|
|
2234
|
+
const res = this.templates[template](context);
|
|
2235
|
+
return res instanceof Error ? await Promise.reject(res) : res;
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2238
|
+
TemplateRenderer = __decorate([
|
|
2239
|
+
singleton(),
|
|
2240
|
+
__metadata("design:paramtypes", [Translator, Configuration])
|
|
2241
|
+
], TemplateRenderer);
|
|
2242
|
+
|
|
2243
|
+
let MailSender = class MailSender {
|
|
2244
|
+
constructor(config, renderer) {
|
|
2245
|
+
this.config = config;
|
|
2246
|
+
this.renderer = renderer;
|
|
2247
|
+
this.transporter = createTransport({
|
|
2248
|
+
host: this.config.resolve("smtpHost"),
|
|
2249
|
+
port: this.config.resolve("smtpPort"),
|
|
2250
|
+
auth: {
|
|
2251
|
+
user: this.config.resolve("smtpUser"),
|
|
2252
|
+
pass: this.config.resolve("smtpPassword"),
|
|
2253
|
+
}
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2256
|
+
get translator() {
|
|
2257
|
+
return this.renderer.translator;
|
|
2258
|
+
}
|
|
2259
|
+
async sendMail(language, options) {
|
|
2260
|
+
const subject = await this.translator.getTranslation(language, options.subject || "-");
|
|
2261
|
+
const html = await this.renderer.render(options.template, language, options.context);
|
|
2262
|
+
return this.transporter.sendMail({
|
|
2263
|
+
from: options.from || this.config.resolve("mailSenderAddress"),
|
|
2264
|
+
to: options.to,
|
|
2265
|
+
attachments: options.attachments,
|
|
2266
|
+
subject,
|
|
2267
|
+
html
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
};
|
|
2271
|
+
MailSender = __decorate([
|
|
2272
|
+
singleton(),
|
|
2273
|
+
__metadata("design:paramtypes", [Configuration, TemplateRenderer])
|
|
2274
|
+
], MailSender);
|
|
2275
|
+
|
|
2276
|
+
let MemoryCache = class MemoryCache {
|
|
2277
|
+
constructor(cache) {
|
|
2278
|
+
this.cache = cache;
|
|
2279
|
+
this.cacheMap = new Map();
|
|
2280
|
+
}
|
|
2281
|
+
async set(key, value, ttl, expirationTimestamp = null, tags = {}) {
|
|
2282
|
+
const now = Math.round(new Date().getTime() / 1000);
|
|
2283
|
+
const expTimestamp = Math.min(isNaN(ttl) ? Number.MAX_SAFE_INTEGER : ttl, 3600);
|
|
2284
|
+
this.cacheMap.set(key, {
|
|
2285
|
+
_id: key,
|
|
2286
|
+
data: value,
|
|
2287
|
+
expirationTimestamp: expTimestamp,
|
|
2288
|
+
expiresAt: now + expTimestamp,
|
|
2289
|
+
});
|
|
2290
|
+
return this.cache.set(key, value, ttl, expirationTimestamp, tags);
|
|
2291
|
+
}
|
|
2292
|
+
async get(key) {
|
|
2293
|
+
let item = this.cacheMap.get(key);
|
|
2294
|
+
const now = Math.round(new Date().getTime() / 1000);
|
|
2295
|
+
let expTimestamp = 3600;
|
|
2296
|
+
if (item && item.expiresAt && item.expiresAt < now) {
|
|
2297
|
+
expTimestamp = item.expirationTimestamp;
|
|
2298
|
+
item = null;
|
|
2299
|
+
}
|
|
2300
|
+
if (!item) {
|
|
2301
|
+
const value = await this.cache.get(key);
|
|
2302
|
+
this.cacheMap.set(key, {
|
|
2303
|
+
_id: key,
|
|
2304
|
+
data: value,
|
|
2305
|
+
expirationTimestamp: expTimestamp,
|
|
2306
|
+
expiresAt: now + expTimestamp,
|
|
2307
|
+
});
|
|
2308
|
+
return value;
|
|
2309
|
+
}
|
|
2310
|
+
return item.data;
|
|
2311
|
+
}
|
|
2312
|
+
async getOrSet(key, valueCb, ttl, expirationTimestamp = null, tags = {}) {
|
|
2313
|
+
try {
|
|
2314
|
+
return await this.get(key);
|
|
2315
|
+
}
|
|
2316
|
+
catch (e) {
|
|
2317
|
+
return await this.set(key, await valueCb(), ttl, expirationTimestamp, tags);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
async delete(key) {
|
|
2321
|
+
this.cacheMap.delete(key);
|
|
2322
|
+
await this.cacheMap.delete(key);
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
MemoryCache = __decorate([
|
|
2326
|
+
injectable(),
|
|
2327
|
+
scoped(Lifecycle.ContainerScoped),
|
|
2328
|
+
__metadata("design:paramtypes", [Cache])
|
|
2329
|
+
], MemoryCache);
|
|
2330
|
+
|
|
2331
|
+
function checkValue(multi, value) {
|
|
2332
|
+
if (multi) {
|
|
2333
|
+
return Array.isArray(value) && value.every(v => {
|
|
2334
|
+
try {
|
|
2335
|
+
const id = new ObjectId$1(v);
|
|
2336
|
+
return id instanceof ObjectId$1;
|
|
2337
|
+
}
|
|
2338
|
+
catch (e) {
|
|
2339
|
+
return false;
|
|
2340
|
+
}
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2343
|
+
if (null === value)
|
|
2344
|
+
return true;
|
|
2345
|
+
try {
|
|
2346
|
+
const id = new ObjectId$1(value);
|
|
2347
|
+
return id instanceof ObjectId$1;
|
|
2348
|
+
}
|
|
2349
|
+
catch (e) {
|
|
2350
|
+
return false;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
let IsFile = class IsFile {
|
|
2354
|
+
validate(value, validationArguments) {
|
|
2355
|
+
const [multi] = (validationArguments.constraints || []);
|
|
2356
|
+
return checkValue(multi, value);
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
IsFile = __decorate([
|
|
2360
|
+
ValidatorConstraint()
|
|
2361
|
+
], IsFile);
|
|
2362
|
+
let IsObjectId = class IsObjectId {
|
|
2363
|
+
validate(value, validationArguments) {
|
|
2364
|
+
const [_, multi] = (validationArguments.constraints || []);
|
|
2365
|
+
return checkValue(multi, value);
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
IsObjectId = __decorate([
|
|
2369
|
+
ValidatorConstraint()
|
|
2370
|
+
], IsObjectId);
|
|
2371
|
+
|
|
2372
|
+
let OpenApi = class OpenApi {
|
|
2373
|
+
constructor(container, customValidation) {
|
|
2374
|
+
this.container = container;
|
|
2375
|
+
this.customValidation = customValidation;
|
|
2376
|
+
this.docs = null;
|
|
2377
|
+
}
|
|
2378
|
+
get apiDocs() {
|
|
2379
|
+
if (!this.docs)
|
|
2380
|
+
this.docs = this.createApiDocs();
|
|
2381
|
+
return this.docs;
|
|
2382
|
+
}
|
|
2383
|
+
get apiDocsStr() {
|
|
2384
|
+
if (!this.docsStr)
|
|
2385
|
+
this.docsStr = JSON.stringify(this.apiDocs);
|
|
2386
|
+
return this.docsStr;
|
|
2387
|
+
}
|
|
2388
|
+
async schemaToExample(src, req) {
|
|
2389
|
+
if (src.$ref) {
|
|
2390
|
+
const schemas = this.apiDocs.components.schemas;
|
|
2391
|
+
const schema = src.$ref
|
|
2392
|
+
.replace("#/components/schemas/", "")
|
|
2393
|
+
.replace("#/definitions/", "");
|
|
2394
|
+
return this.schemaToExample(schemas[schema], req);
|
|
2395
|
+
}
|
|
2396
|
+
let schema = src;
|
|
2397
|
+
if (schema.oneOf) {
|
|
2398
|
+
schema = Object.assign({}, schema, schema.oneOf[0]);
|
|
2399
|
+
}
|
|
2400
|
+
if (schema.type === "object") {
|
|
2401
|
+
const result = {};
|
|
2402
|
+
await Promise.all(Object.keys(schema.properties).map(async (key) => {
|
|
2403
|
+
result[key] = await this.schemaToExample(schema.properties[key], req);
|
|
2404
|
+
}));
|
|
2405
|
+
return result;
|
|
2406
|
+
}
|
|
2407
|
+
if (schema.type === "array") {
|
|
2408
|
+
return [await this.schemaToExample(schema.items, req)];
|
|
2409
|
+
}
|
|
2410
|
+
if (schema.type === "string") {
|
|
2411
|
+
if (isDefined(schema.default)) {
|
|
2412
|
+
if (isFunction(schema.default)) {
|
|
2413
|
+
return schema.default(this.container);
|
|
2414
|
+
}
|
|
2415
|
+
return schema.default;
|
|
2416
|
+
}
|
|
2417
|
+
if (schema.format == "date") {
|
|
2418
|
+
return new Date().toISOString().substr(0, 10);
|
|
2419
|
+
}
|
|
2420
|
+
if (schema.format == "date-time") {
|
|
2421
|
+
return new Date().toISOString();
|
|
2422
|
+
}
|
|
2423
|
+
if (schema.enum) {
|
|
2424
|
+
return schema.enum[0];
|
|
2425
|
+
}
|
|
2426
|
+
return "string";
|
|
2427
|
+
}
|
|
2428
|
+
if (schema.type === "number") {
|
|
2429
|
+
return schema.default ?? 0;
|
|
2430
|
+
}
|
|
2431
|
+
else if (schema.type === "boolean") {
|
|
2432
|
+
return schema.default ?? false;
|
|
2433
|
+
}
|
|
2434
|
+
else {
|
|
2435
|
+
return schema.default ?? null;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
createApiDocs() {
|
|
2439
|
+
const storage = getMetadataArgsStorage();
|
|
2440
|
+
const docs = routingControllersToSpec(storage);
|
|
2441
|
+
docs.basePath = "/api/";
|
|
2442
|
+
docs.definitions = validationMetadatasToSchemas({
|
|
2443
|
+
additionalConverters: {
|
|
2444
|
+
[ValidationTypes.CUSTOM_VALIDATION]: (meta, options) => {
|
|
2445
|
+
const res = isFunction(this.customValidation) ? this.customValidation(meta, options) : this.customValidation;
|
|
2446
|
+
if (isObject(res))
|
|
2447
|
+
return res;
|
|
2448
|
+
const constraints = meta.constraints || [];
|
|
2449
|
+
if (meta.constraintCls === IsFile) {
|
|
2450
|
+
return {
|
|
2451
|
+
multi: constraints[0] || false,
|
|
2452
|
+
type: "file"
|
|
2453
|
+
};
|
|
2336
2454
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2455
|
+
if (meta.constraintCls === IsObjectId) {
|
|
2456
|
+
return {
|
|
2457
|
+
endpoint: constraints[0] || false,
|
|
2458
|
+
multi: constraints[1] || false,
|
|
2459
|
+
type: "list"
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
return null;
|
|
2344
2463
|
}
|
|
2345
|
-
|
|
2346
|
-
});
|
|
2464
|
+
}
|
|
2347
2465
|
});
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
await this.init();
|
|
2351
|
-
await this.translator.getDictionary(language);
|
|
2352
|
-
if (!this.templates[template]) {
|
|
2353
|
-
return Promise.reject(`Template not found with name: ${template}`);
|
|
2354
|
-
}
|
|
2355
|
-
context = Object.assign({ language }, context || {});
|
|
2356
|
-
const res = this.templates[template](context);
|
|
2357
|
-
return res instanceof Error ? await Promise.reject(res) : res;
|
|
2466
|
+
docs.components.schemas = docs.definitions;
|
|
2467
|
+
return docs;
|
|
2358
2468
|
}
|
|
2359
2469
|
};
|
|
2360
|
-
|
|
2361
|
-
singleton()
|
|
2362
|
-
|
|
2470
|
+
OpenApi = __decorate([
|
|
2471
|
+
singleton(),
|
|
2472
|
+
__param(0, inject(DI_CONTAINER)),
|
|
2473
|
+
__param(1, inject(OPENAPI_VALIDATION)),
|
|
2474
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
2475
|
+
], OpenApi);
|
|
2363
2476
|
|
|
2364
2477
|
let TerminalManager = class TerminalManager {
|
|
2365
2478
|
constructor(logger, config, commands) {
|
|
@@ -2429,7 +2542,9 @@ let TerminalManager = class TerminalManager {
|
|
|
2429
2542
|
};
|
|
2430
2543
|
TerminalManager = __decorate([
|
|
2431
2544
|
singleton(),
|
|
2432
|
-
__param(2, injectAll(TERMINAL_COMMAND))
|
|
2545
|
+
__param(2, injectAll(TERMINAL_COMMAND)),
|
|
2546
|
+
__metadata("design:paramtypes", [Logger,
|
|
2547
|
+
Configuration, Array])
|
|
2433
2548
|
], TerminalManager);
|
|
2434
2549
|
|
|
2435
2550
|
let TokenGenerator = class TokenGenerator {
|
|
@@ -2460,97 +2575,10 @@ let TokenGenerator = class TokenGenerator {
|
|
|
2460
2575
|
}
|
|
2461
2576
|
};
|
|
2462
2577
|
TokenGenerator = __decorate([
|
|
2463
|
-
singleton()
|
|
2578
|
+
singleton(),
|
|
2579
|
+
__metadata("design:paramtypes", [])
|
|
2464
2580
|
], TokenGenerator);
|
|
2465
2581
|
|
|
2466
|
-
let TranslationProvider = class TranslationProvider {
|
|
2467
|
-
constructor(config, cache) {
|
|
2468
|
-
this.config = config;
|
|
2469
|
-
this.cache = cache;
|
|
2470
|
-
}
|
|
2471
|
-
getDictionary(language) {
|
|
2472
|
-
return this.cache.getOrSet(`translations-${language}`, async () => {
|
|
2473
|
-
try {
|
|
2474
|
-
const url = this.config.resolve("translationsTemplate")
|
|
2475
|
-
.replace(`__lang__`, language)
|
|
2476
|
-
.replace(`[lang]`, language);
|
|
2477
|
-
const data = await axios.get(url).then(t => t.data);
|
|
2478
|
-
if (isObject(data[language])) {
|
|
2479
|
-
return data[language];
|
|
2480
|
-
}
|
|
2481
|
-
return data;
|
|
2482
|
-
}
|
|
2483
|
-
catch (e) {
|
|
2484
|
-
return {
|
|
2485
|
-
message: `${e}`
|
|
2486
|
-
};
|
|
2487
|
-
}
|
|
2488
|
-
}, 5 * 60);
|
|
2489
|
-
}
|
|
2490
|
-
};
|
|
2491
|
-
TranslationProvider = __decorate([
|
|
2492
|
-
singleton()
|
|
2493
|
-
], TranslationProvider);
|
|
2494
|
-
|
|
2495
|
-
let Translator = class Translator {
|
|
2496
|
-
constructor(translationProvider) {
|
|
2497
|
-
this.translationProvider = translationProvider;
|
|
2498
|
-
this.dictionaries = {};
|
|
2499
|
-
}
|
|
2500
|
-
async getDictionary(language) {
|
|
2501
|
-
this.dictionaries[language] = await this.translationProvider.getDictionary(language);
|
|
2502
|
-
return this.dictionaries[language];
|
|
2503
|
-
}
|
|
2504
|
-
getTranslationSync(language, key, params) {
|
|
2505
|
-
if (!isString(key) || !key.length) {
|
|
2506
|
-
throw new Error(`Parameter "key" required`);
|
|
2507
|
-
}
|
|
2508
|
-
const dictionary = this.dictionaries[language];
|
|
2509
|
-
const translation = getValue(dictionary, key, key) || key;
|
|
2510
|
-
return this.interpolate(translation, params);
|
|
2511
|
-
}
|
|
2512
|
-
getTranslation(language, key, params) {
|
|
2513
|
-
if (!isString(key) || !key.length) {
|
|
2514
|
-
throw new Error(`Parameter "key" required`);
|
|
2515
|
-
}
|
|
2516
|
-
return this.getDictionary(language).then(dictionary => {
|
|
2517
|
-
const translation = getValue(dictionary, key, key) || key;
|
|
2518
|
-
return this.interpolate(translation, params);
|
|
2519
|
-
});
|
|
2520
|
-
}
|
|
2521
|
-
getTranslations(language, ...keys) {
|
|
2522
|
-
return new Promise(resolve => {
|
|
2523
|
-
Promise.all(keys.map(key => this.getTranslation(language, key))).then(translations => {
|
|
2524
|
-
resolve(keys.reduce((result, key, i) => {
|
|
2525
|
-
result[key] = translations[i];
|
|
2526
|
-
return result;
|
|
2527
|
-
}, {}));
|
|
2528
|
-
});
|
|
2529
|
-
});
|
|
2530
|
-
}
|
|
2531
|
-
interpolate(expr, params) {
|
|
2532
|
-
if (typeof expr === "string") {
|
|
2533
|
-
return this.interpolateString(expr, params);
|
|
2534
|
-
}
|
|
2535
|
-
if (typeof expr === "function") {
|
|
2536
|
-
return expr(params);
|
|
2537
|
-
}
|
|
2538
|
-
return expr;
|
|
2539
|
-
}
|
|
2540
|
-
interpolateString(expr, params) {
|
|
2541
|
-
if (!expr || !params)
|
|
2542
|
-
return expr;
|
|
2543
|
-
return expr.replace(/{{\s?([^{}\s]*)\s?}}/g, (substring, b) => {
|
|
2544
|
-
const r = getValue(params, b);
|
|
2545
|
-
return isDefined(r) ? r : substring;
|
|
2546
|
-
});
|
|
2547
|
-
}
|
|
2548
|
-
};
|
|
2549
|
-
Translator = __decorate([
|
|
2550
|
-
injectable(),
|
|
2551
|
-
singleton()
|
|
2552
|
-
], Translator);
|
|
2553
|
-
|
|
2554
2582
|
const sampleUser = {
|
|
2555
2583
|
id: "5a3cdf7c6a9cf0ba32feccdf",
|
|
2556
2584
|
email: "admin@site.com",
|
|
@@ -2575,6 +2603,66 @@ UserManager = __decorate([
|
|
|
2575
2603
|
scoped(Lifecycle.ContainerScoped)
|
|
2576
2604
|
], UserManager);
|
|
2577
2605
|
|
|
2606
|
+
class AssetImageParams {
|
|
2607
|
+
constructor() {
|
|
2608
|
+
this.rotation = 0;
|
|
2609
|
+
this.canvasScaleX = 1;
|
|
2610
|
+
this.canvasScaleY = 1;
|
|
2611
|
+
this.scaleX = 1;
|
|
2612
|
+
this.scaleY = 1;
|
|
2613
|
+
this.lazy = false;
|
|
2614
|
+
this.crop = false;
|
|
2615
|
+
this.cropBefore = false;
|
|
2616
|
+
this.cropAfter = false;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
__decorate([
|
|
2620
|
+
Min(-360),
|
|
2621
|
+
Max(360),
|
|
2622
|
+
IsOptional(),
|
|
2623
|
+
__metadata("design:type", Number)
|
|
2624
|
+
], AssetImageParams.prototype, "rotation", void 0);
|
|
2625
|
+
__decorate([
|
|
2626
|
+
Min(0.0001),
|
|
2627
|
+
IsOptional(),
|
|
2628
|
+
__metadata("design:type", Number)
|
|
2629
|
+
], AssetImageParams.prototype, "canvasScaleX", void 0);
|
|
2630
|
+
__decorate([
|
|
2631
|
+
Min(0.0001),
|
|
2632
|
+
IsOptional(),
|
|
2633
|
+
__metadata("design:type", Number)
|
|
2634
|
+
], AssetImageParams.prototype, "canvasScaleY", void 0);
|
|
2635
|
+
__decorate([
|
|
2636
|
+
Min(0.0001),
|
|
2637
|
+
IsOptional(),
|
|
2638
|
+
__metadata("design:type", Number)
|
|
2639
|
+
], AssetImageParams.prototype, "scaleX", void 0);
|
|
2640
|
+
__decorate([
|
|
2641
|
+
Min(0.0001),
|
|
2642
|
+
IsOptional(),
|
|
2643
|
+
__metadata("design:type", Number)
|
|
2644
|
+
], AssetImageParams.prototype, "scaleY", void 0);
|
|
2645
|
+
__decorate([
|
|
2646
|
+
IsBoolean(),
|
|
2647
|
+
IsOptional(),
|
|
2648
|
+
__metadata("design:type", Boolean)
|
|
2649
|
+
], AssetImageParams.prototype, "lazy", void 0);
|
|
2650
|
+
__decorate([
|
|
2651
|
+
IsBoolean(),
|
|
2652
|
+
IsOptional(),
|
|
2653
|
+
__metadata("design:type", Boolean)
|
|
2654
|
+
], AssetImageParams.prototype, "crop", void 0);
|
|
2655
|
+
__decorate([
|
|
2656
|
+
IsBoolean(),
|
|
2657
|
+
IsOptional(),
|
|
2658
|
+
__metadata("design:type", Boolean)
|
|
2659
|
+
], AssetImageParams.prototype, "cropBefore", void 0);
|
|
2660
|
+
__decorate([
|
|
2661
|
+
IsBoolean(),
|
|
2662
|
+
IsOptional(),
|
|
2663
|
+
__metadata("design:type", Boolean)
|
|
2664
|
+
], AssetImageParams.prototype, "cropAfter", void 0);
|
|
2665
|
+
|
|
2578
2666
|
let AssetsController = class AssetsController {
|
|
2579
2667
|
constructor(assets, assetResolver) {
|
|
2580
2668
|
this.assets = assets;
|
|
@@ -2655,46 +2743,68 @@ let AssetsController = class AssetsController {
|
|
|
2655
2743
|
__decorate([
|
|
2656
2744
|
Authorized(),
|
|
2657
2745
|
Post(""),
|
|
2658
|
-
__param(0, UploadedFile("file"))
|
|
2746
|
+
__param(0, UploadedFile("file")),
|
|
2747
|
+
__metadata("design:type", Function),
|
|
2748
|
+
__metadata("design:paramtypes", [Object]),
|
|
2749
|
+
__metadata("design:returntype", Promise)
|
|
2659
2750
|
], AssetsController.prototype, "upload", null);
|
|
2660
2751
|
__decorate([
|
|
2661
2752
|
Authorized(),
|
|
2662
2753
|
Post("url"),
|
|
2663
|
-
__param(0, Body())
|
|
2754
|
+
__param(0, Body()),
|
|
2755
|
+
__metadata("design:type", Function),
|
|
2756
|
+
__metadata("design:paramtypes", [Object]),
|
|
2757
|
+
__metadata("design:returntype", Promise)
|
|
2664
2758
|
], AssetsController.prototype, "uploadUrl", null);
|
|
2665
2759
|
__decorate([
|
|
2666
2760
|
Get("/:id"),
|
|
2667
2761
|
__param(0, Param("id")),
|
|
2668
2762
|
__param(1, QueryParam("lazy")),
|
|
2669
|
-
__param(2, Res())
|
|
2763
|
+
__param(2, Res()),
|
|
2764
|
+
__metadata("design:type", Function),
|
|
2765
|
+
__metadata("design:paramtypes", [String, Boolean, Object]),
|
|
2766
|
+
__metadata("design:returntype", Promise)
|
|
2670
2767
|
], AssetsController.prototype, "getFile", null);
|
|
2671
2768
|
__decorate([
|
|
2672
2769
|
Get("/image/:id/:rotation"),
|
|
2673
2770
|
__param(0, Param("id")),
|
|
2674
2771
|
__param(1, QueryParams()),
|
|
2675
2772
|
__param(2, Res()),
|
|
2676
|
-
__param(3, Param("rotation"))
|
|
2773
|
+
__param(3, Param("rotation")),
|
|
2774
|
+
__metadata("design:type", Function),
|
|
2775
|
+
__metadata("design:paramtypes", [String, AssetImageParams, Object, Number]),
|
|
2776
|
+
__metadata("design:returntype", Promise)
|
|
2677
2777
|
], AssetsController.prototype, "getImageRotation", null);
|
|
2678
2778
|
__decorate([
|
|
2679
2779
|
Get("/image/:id"),
|
|
2680
2780
|
__param(0, Param("id")),
|
|
2681
2781
|
__param(1, QueryParams()),
|
|
2682
|
-
__param(2, Res())
|
|
2782
|
+
__param(2, Res()),
|
|
2783
|
+
__metadata("design:type", Function),
|
|
2784
|
+
__metadata("design:paramtypes", [String, AssetImageParams, Object]),
|
|
2785
|
+
__metadata("design:returntype", Promise)
|
|
2683
2786
|
], AssetsController.prototype, "getImage", null);
|
|
2684
2787
|
__decorate([
|
|
2685
2788
|
Get("/by-name/:name"),
|
|
2686
2789
|
__param(0, Param("name")),
|
|
2687
|
-
__param(1, Res())
|
|
2790
|
+
__param(1, Res()),
|
|
2791
|
+
__metadata("design:type", Function),
|
|
2792
|
+
__metadata("design:paramtypes", [String, Object]),
|
|
2793
|
+
__metadata("design:returntype", Promise)
|
|
2688
2794
|
], AssetsController.prototype, "getFileByName", null);
|
|
2689
2795
|
__decorate([
|
|
2690
2796
|
Get("/by-name/image/:name"),
|
|
2691
2797
|
__param(0, Param("name")),
|
|
2692
2798
|
__param(1, QueryParams()),
|
|
2693
|
-
__param(2, Res())
|
|
2799
|
+
__param(2, Res()),
|
|
2800
|
+
__metadata("design:type", Function),
|
|
2801
|
+
__metadata("design:paramtypes", [String, AssetImageParams, Object]),
|
|
2802
|
+
__metadata("design:returntype", Promise)
|
|
2694
2803
|
], AssetsController.prototype, "getImageByName", null);
|
|
2695
2804
|
AssetsController = __decorate([
|
|
2696
2805
|
injectable(),
|
|
2697
|
-
Controller("/assets")
|
|
2806
|
+
Controller("/assets"),
|
|
2807
|
+
__metadata("design:paramtypes", [Assets, AssetResolver])
|
|
2698
2808
|
], AssetsController);
|
|
2699
2809
|
|
|
2700
2810
|
let AuthController = class AuthController {
|
|
@@ -2725,16 +2835,23 @@ let AuthController = class AuthController {
|
|
|
2725
2835
|
__decorate([
|
|
2726
2836
|
Post("/login"),
|
|
2727
2837
|
__param(0, Body()),
|
|
2728
|
-
__param(1, Res())
|
|
2838
|
+
__param(1, Res()),
|
|
2839
|
+
__metadata("design:type", Function),
|
|
2840
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
2841
|
+
__metadata("design:returntype", Promise)
|
|
2729
2842
|
], AuthController.prototype, "login", null);
|
|
2730
2843
|
__decorate([
|
|
2731
2844
|
Authorized(),
|
|
2732
2845
|
Get("/user"),
|
|
2733
|
-
__param(0, CurrentUser())
|
|
2846
|
+
__param(0, CurrentUser()),
|
|
2847
|
+
__metadata("design:type", Function),
|
|
2848
|
+
__metadata("design:paramtypes", [Object]),
|
|
2849
|
+
__metadata("design:returntype", void 0)
|
|
2734
2850
|
], AuthController.prototype, "getProfile", null);
|
|
2735
2851
|
AuthController = __decorate([
|
|
2736
2852
|
injectable(),
|
|
2737
|
-
Controller()
|
|
2853
|
+
Controller(),
|
|
2854
|
+
__metadata("design:paramtypes", [Configuration, UserManager])
|
|
2738
2855
|
], AuthController);
|
|
2739
2856
|
|
|
2740
2857
|
let GalleryController = class GalleryController {
|
|
@@ -2747,11 +2864,15 @@ let GalleryController = class GalleryController {
|
|
|
2747
2864
|
};
|
|
2748
2865
|
__decorate([
|
|
2749
2866
|
Get("/:id"),
|
|
2750
|
-
__param(0, Param("id"))
|
|
2867
|
+
__param(0, Param("id")),
|
|
2868
|
+
__metadata("design:type", Function),
|
|
2869
|
+
__metadata("design:paramtypes", [String]),
|
|
2870
|
+
__metadata("design:returntype", void 0)
|
|
2751
2871
|
], GalleryController.prototype, "getFile", null);
|
|
2752
2872
|
GalleryController = __decorate([
|
|
2753
2873
|
injectable(),
|
|
2754
|
-
Controller("/gallery")
|
|
2874
|
+
Controller("/gallery"),
|
|
2875
|
+
__metadata("design:paramtypes", [GalleryCache])
|
|
2755
2876
|
], GalleryController);
|
|
2756
2877
|
|
|
2757
2878
|
let ProgressesController = class ProgressesController {
|
|
@@ -2772,11 +2893,15 @@ let ProgressesController = class ProgressesController {
|
|
|
2772
2893
|
};
|
|
2773
2894
|
__decorate([
|
|
2774
2895
|
Get("/:id"),
|
|
2775
|
-
__param(0, Param("id"))
|
|
2896
|
+
__param(0, Param("id")),
|
|
2897
|
+
__metadata("design:type", Function),
|
|
2898
|
+
__metadata("design:paramtypes", [String]),
|
|
2899
|
+
__metadata("design:returntype", Promise)
|
|
2776
2900
|
], ProgressesController.prototype, "getProgress", null);
|
|
2777
2901
|
ProgressesController = __decorate([
|
|
2778
2902
|
injectable(),
|
|
2779
|
-
Controller("/progresses")
|
|
2903
|
+
Controller("/progresses"),
|
|
2904
|
+
__metadata("design:paramtypes", [Progresses, Configuration])
|
|
2780
2905
|
], ProgressesController);
|
|
2781
2906
|
|
|
2782
2907
|
// Add a comment hint for webstorm to style the string as css
|
|
@@ -2951,19 +3076,29 @@ let TerminalController$1 = class TerminalController {
|
|
|
2951
3076
|
};
|
|
2952
3077
|
__decorate([
|
|
2953
3078
|
Get("/terminal"),
|
|
2954
|
-
Header("Content-Type", "text/html")
|
|
3079
|
+
Header("Content-Type", "text/html"),
|
|
3080
|
+
__metadata("design:type", Function),
|
|
3081
|
+
__metadata("design:paramtypes", []),
|
|
3082
|
+
__metadata("design:returntype", void 0)
|
|
2955
3083
|
], TerminalController$1.prototype, "terminal", null);
|
|
2956
3084
|
__decorate([
|
|
2957
3085
|
Get("/console"),
|
|
2958
|
-
Header("Content-Type", "text/html")
|
|
3086
|
+
Header("Content-Type", "text/html"),
|
|
3087
|
+
__metadata("design:type", Function),
|
|
3088
|
+
__metadata("design:paramtypes", []),
|
|
3089
|
+
__metadata("design:returntype", void 0)
|
|
2959
3090
|
], TerminalController$1.prototype, "console", null);
|
|
2960
3091
|
__decorate([
|
|
2961
3092
|
Get(),
|
|
2962
|
-
Header("Content-Type", "text/html")
|
|
3093
|
+
Header("Content-Type", "text/html"),
|
|
3094
|
+
__metadata("design:type", Function),
|
|
3095
|
+
__metadata("design:paramtypes", [String]),
|
|
3096
|
+
__metadata("design:returntype", String)
|
|
2963
3097
|
], TerminalController$1.prototype, "generateClient", null);
|
|
2964
3098
|
TerminalController$1 = __decorate([
|
|
2965
3099
|
injectable(),
|
|
2966
|
-
Controller()
|
|
3100
|
+
Controller(),
|
|
3101
|
+
__metadata("design:paramtypes", [Configuration])
|
|
2967
3102
|
], TerminalController$1);
|
|
2968
3103
|
|
|
2969
3104
|
let ErrorHandlerMiddleware = class ErrorHandlerMiddleware {
|
|
@@ -3032,7 +3167,8 @@ let ErrorHandlerMiddleware = class ErrorHandlerMiddleware {
|
|
|
3032
3167
|
};
|
|
3033
3168
|
ErrorHandlerMiddleware = __decorate([
|
|
3034
3169
|
injectable(),
|
|
3035
|
-
Middleware({ type: "after" })
|
|
3170
|
+
Middleware({ type: "after" }),
|
|
3171
|
+
__metadata("design:paramtypes", [Configuration, Translator])
|
|
3036
3172
|
], ErrorHandlerMiddleware);
|
|
3037
3173
|
|
|
3038
3174
|
let ContainerMiddleware = class ContainerMiddleware {
|
|
@@ -3047,7 +3183,8 @@ let ContainerMiddleware = class ContainerMiddleware {
|
|
|
3047
3183
|
ContainerMiddleware = __decorate([
|
|
3048
3184
|
injectable(),
|
|
3049
3185
|
Middleware({ type: "before" }),
|
|
3050
|
-
__param(0, inject(DI_CONTAINER))
|
|
3186
|
+
__param(0, inject(DI_CONTAINER)),
|
|
3187
|
+
__metadata("design:paramtypes", [Object])
|
|
3051
3188
|
], ContainerMiddleware);
|
|
3052
3189
|
|
|
3053
3190
|
let LanguageMiddleware = class LanguageMiddleware {
|
|
@@ -3061,7 +3198,8 @@ let LanguageMiddleware = class LanguageMiddleware {
|
|
|
3061
3198
|
};
|
|
3062
3199
|
LanguageMiddleware = __decorate([
|
|
3063
3200
|
injectable(),
|
|
3064
|
-
Middleware({ type: "before" })
|
|
3201
|
+
Middleware({ type: "before" }),
|
|
3202
|
+
__metadata("design:paramtypes", [Configuration])
|
|
3065
3203
|
], LanguageMiddleware);
|
|
3066
3204
|
|
|
3067
3205
|
let RequestEndedMiddleware = class RequestEndedMiddleware {
|
|
@@ -3079,7 +3217,8 @@ let RequestEndedMiddleware = class RequestEndedMiddleware {
|
|
|
3079
3217
|
};
|
|
3080
3218
|
RequestEndedMiddleware = __decorate([
|
|
3081
3219
|
injectable(),
|
|
3082
|
-
Middleware({ type: "after" })
|
|
3220
|
+
Middleware({ type: "after" }),
|
|
3221
|
+
__metadata("design:paramtypes", [Logger])
|
|
3083
3222
|
], RequestEndedMiddleware);
|
|
3084
3223
|
|
|
3085
3224
|
let RequestStartedMiddleware = class RequestStartedMiddleware {
|
|
@@ -3095,7 +3234,8 @@ let RequestStartedMiddleware = class RequestStartedMiddleware {
|
|
|
3095
3234
|
};
|
|
3096
3235
|
RequestStartedMiddleware = __decorate([
|
|
3097
3236
|
injectable(),
|
|
3098
|
-
Middleware({ type: "before" })
|
|
3237
|
+
Middleware({ type: "before" }),
|
|
3238
|
+
__metadata("design:paramtypes", [Logger])
|
|
3099
3239
|
], RequestStartedMiddleware);
|
|
3100
3240
|
|
|
3101
3241
|
let ProgressController = class ProgressController {
|
|
@@ -3131,17 +3271,24 @@ let ProgressController = class ProgressController {
|
|
|
3131
3271
|
__decorate([
|
|
3132
3272
|
OnMessage("background-progress"),
|
|
3133
3273
|
__param(0, ConnectedSocket()),
|
|
3134
|
-
__param(1, MessageBody())
|
|
3274
|
+
__param(1, MessageBody()),
|
|
3275
|
+
__metadata("design:type", Function),
|
|
3276
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
3277
|
+
__metadata("design:returntype", Promise)
|
|
3135
3278
|
], ProgressController.prototype, "advanceProgress", null);
|
|
3136
3279
|
__decorate([
|
|
3137
3280
|
OnMessage("background-progress-interest"),
|
|
3138
3281
|
__param(0, ConnectedSocket()),
|
|
3139
|
-
__param(1, MessageBody())
|
|
3282
|
+
__param(1, MessageBody()),
|
|
3283
|
+
__metadata("design:type", Function),
|
|
3284
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
3285
|
+
__metadata("design:returntype", Promise)
|
|
3140
3286
|
], ProgressController.prototype, "setProgressInterest", null);
|
|
3141
3287
|
ProgressController = __decorate([
|
|
3142
3288
|
singleton(),
|
|
3143
3289
|
SocketController(),
|
|
3144
|
-
__param(1, inject(SOCKET_SERVER))
|
|
3290
|
+
__param(1, inject(SOCKET_SERVER)),
|
|
3291
|
+
__metadata("design:paramtypes", [Progresses, Server])
|
|
3145
3292
|
], ProgressController);
|
|
3146
3293
|
|
|
3147
3294
|
class Terminal {
|
|
@@ -3252,21 +3399,31 @@ let TerminalController = class TerminalController {
|
|
|
3252
3399
|
};
|
|
3253
3400
|
__decorate([
|
|
3254
3401
|
OnMessage("terminal-init"),
|
|
3255
|
-
__param(0, ConnectedSocket())
|
|
3402
|
+
__param(0, ConnectedSocket()),
|
|
3403
|
+
__metadata("design:type", Function),
|
|
3404
|
+
__metadata("design:paramtypes", [Object]),
|
|
3405
|
+
__metadata("design:returntype", Promise)
|
|
3256
3406
|
], TerminalController.prototype, "terminalInit", null);
|
|
3257
3407
|
__decorate([
|
|
3258
3408
|
OnMessage("terminal-data"),
|
|
3259
3409
|
__param(0, ConnectedSocket()),
|
|
3260
|
-
__param(1, MessageBody())
|
|
3410
|
+
__param(1, MessageBody()),
|
|
3411
|
+
__metadata("design:type", Function),
|
|
3412
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
3413
|
+
__metadata("design:returntype", Promise)
|
|
3261
3414
|
], TerminalController.prototype, "terminalData", null);
|
|
3262
3415
|
__decorate([
|
|
3263
3416
|
OnMessage("terminal-upload"),
|
|
3264
3417
|
__param(0, ConnectedSocket()),
|
|
3265
|
-
__param(1, MessageBody())
|
|
3418
|
+
__param(1, MessageBody()),
|
|
3419
|
+
__metadata("design:type", Function),
|
|
3420
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
3421
|
+
__metadata("design:returntype", Promise)
|
|
3266
3422
|
], TerminalController.prototype, "terminalUpload", null);
|
|
3267
3423
|
TerminalController = __decorate([
|
|
3268
3424
|
singleton(),
|
|
3269
|
-
SocketController()
|
|
3425
|
+
SocketController(),
|
|
3426
|
+
__metadata("design:paramtypes", [TerminalManager])
|
|
3270
3427
|
], TerminalController);
|
|
3271
3428
|
|
|
3272
3429
|
let CompressionMiddleware = class CompressionMiddleware {
|
|
@@ -3529,7 +3686,8 @@ let FixturesCommand = class FixturesCommand {
|
|
|
3529
3686
|
};
|
|
3530
3687
|
FixturesCommand = __decorate([
|
|
3531
3688
|
injectable(),
|
|
3532
|
-
scoped(Lifecycle.ContainerScoped)
|
|
3689
|
+
scoped(Lifecycle.ContainerScoped),
|
|
3690
|
+
__metadata("design:paramtypes", [Fixtures])
|
|
3533
3691
|
], FixturesCommand);
|
|
3534
3692
|
|
|
3535
3693
|
const commands = [
|
|
@@ -3537,57 +3695,6 @@ const commands = [
|
|
|
3537
3695
|
FixturesCommand
|
|
3538
3696
|
];
|
|
3539
3697
|
|
|
3540
|
-
class AssetImageParams {
|
|
3541
|
-
constructor() {
|
|
3542
|
-
this.rotation = 0;
|
|
3543
|
-
this.canvasScaleX = 1;
|
|
3544
|
-
this.canvasScaleY = 1;
|
|
3545
|
-
this.scaleX = 1;
|
|
3546
|
-
this.scaleY = 1;
|
|
3547
|
-
this.lazy = false;
|
|
3548
|
-
this.crop = false;
|
|
3549
|
-
this.cropBefore = false;
|
|
3550
|
-
this.cropAfter = false;
|
|
3551
|
-
}
|
|
3552
|
-
}
|
|
3553
|
-
__decorate([
|
|
3554
|
-
Min(-360),
|
|
3555
|
-
Max(360),
|
|
3556
|
-
IsOptional()
|
|
3557
|
-
], AssetImageParams.prototype, "rotation", void 0);
|
|
3558
|
-
__decorate([
|
|
3559
|
-
Min(0.0001),
|
|
3560
|
-
IsOptional()
|
|
3561
|
-
], AssetImageParams.prototype, "canvasScaleX", void 0);
|
|
3562
|
-
__decorate([
|
|
3563
|
-
Min(0.0001),
|
|
3564
|
-
IsOptional()
|
|
3565
|
-
], AssetImageParams.prototype, "canvasScaleY", void 0);
|
|
3566
|
-
__decorate([
|
|
3567
|
-
Min(0.0001),
|
|
3568
|
-
IsOptional()
|
|
3569
|
-
], AssetImageParams.prototype, "scaleX", void 0);
|
|
3570
|
-
__decorate([
|
|
3571
|
-
Min(0.0001),
|
|
3572
|
-
IsOptional()
|
|
3573
|
-
], AssetImageParams.prototype, "scaleY", void 0);
|
|
3574
|
-
__decorate([
|
|
3575
|
-
IsBoolean(),
|
|
3576
|
-
IsOptional()
|
|
3577
|
-
], AssetImageParams.prototype, "lazy", void 0);
|
|
3578
|
-
__decorate([
|
|
3579
|
-
IsBoolean(),
|
|
3580
|
-
IsOptional()
|
|
3581
|
-
], AssetImageParams.prototype, "crop", void 0);
|
|
3582
|
-
__decorate([
|
|
3583
|
-
IsBoolean(),
|
|
3584
|
-
IsOptional()
|
|
3585
|
-
], AssetImageParams.prototype, "cropBefore", void 0);
|
|
3586
|
-
__decorate([
|
|
3587
|
-
IsBoolean(),
|
|
3588
|
-
IsOptional()
|
|
3589
|
-
], AssetImageParams.prototype, "cropAfter", void 0);
|
|
3590
|
-
|
|
3591
3698
|
class BaseDoc {
|
|
3592
3699
|
/**
|
|
3593
3700
|
* Casts this to DocumentType<this> to allow using document methods in get/set-s
|