@stemy/backend 3.2.0 → 3.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import { dirname, basename, join, resolve } from 'path';
2
2
  import { json } from 'body-parser';
3
3
  import { sign, verify } from 'jsonwebtoken';
4
4
  import { injectable, scoped, Lifecycle, injectAll, singleton, inject, isFactoryProvider, container } from 'tsyringe';
5
- import { createParamDecorator, BadRequestError, HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Body, Get, Param, QueryParams, Res, QueryParam, Controller, CurrentUser, Middleware, useContainer, useExpressServer } from 'routing-controllers';
5
+ import { createParamDecorator, BadRequestError, HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Body, Get, Param, QueryParam, Res, QueryParams, Controller, CurrentUser, Middleware, useContainer, useExpressServer } from 'routing-controllers';
6
6
  import { OnMessage, ConnectedSocket, MessageBody, SocketController, Middleware as Middleware$1, useContainer as useContainer$1, useSocketServer } from 'socket-controllers';
7
7
  import { routingControllersToSpec } from 'routing-controllers-openapi';
8
8
  import { defaultMetadataStorage } from 'class-transformer/storage';
@@ -15,11 +15,11 @@ import { canReportError } from 'rxjs/internal/util/canReportError';
15
15
  import { mkdir, unlink, readFile as readFile$1, writeFile as writeFile$1, lstat, readdir, access, constants, lstatSync, readFileSync, existsSync } from 'fs';
16
16
  import { Types, model, connect } from 'mongoose';
17
17
  import { getValue as getValue$1, setValue } from 'mongoose/lib/utils';
18
- import { PassThrough, Readable } from 'stream';
18
+ import { Readable, PassThrough } from 'stream';
19
19
  import { ObjectId } from 'bson';
20
+ import sharp_ from 'sharp';
20
21
  import fontKit_ from 'fontkit';
21
22
  import { fromBuffer } from 'file-type';
22
- import sharp_ from 'sharp';
23
23
  import axios from 'axios';
24
24
  import { GridFSBucket } from 'mongodb';
25
25
  import dotenv from 'dotenv';
@@ -44,6 +44,7 @@ var __awaiter$w = (this && this.__awaiter) || function (thisArg, _arguments, P,
44
44
  step((generator = generator.apply(thisArg, _arguments || [])).next());
45
45
  });
46
46
  };
47
+ const sharp$3 = sharp_;
47
48
  const diContainers = {
48
49
  appContainer: null
49
50
  };
@@ -112,6 +113,9 @@ function lcFirst(value) {
112
113
  return "";
113
114
  return value[0].toLowerCase() + value.substr(1);
114
115
  }
116
+ function isObjectId(id) {
117
+ return typeof id === "string" && id.length == 24 && !isNaN(Number("0x" + id));
118
+ }
115
119
  function firstItem(value) {
116
120
  return value[0];
117
121
  }
@@ -301,6 +305,102 @@ function paginateAggregations(model, aggregations, params, metaProjection = {})
301
305
  return pagination;
302
306
  });
303
307
  }
308
+ const cropInterface = {
309
+ x: "number",
310
+ y: "number",
311
+ w: "number",
312
+ h: "number"
313
+ };
314
+ function toCropRegion(cropInfo) {
315
+ let crop = cropInfo;
316
+ if (isString(cropInfo)) {
317
+ try {
318
+ crop = JSON.parse(cropInfo);
319
+ }
320
+ catch (e) {
321
+ return null;
322
+ }
323
+ }
324
+ if (!isInterface(crop, cropInterface))
325
+ return null;
326
+ return {
327
+ width: Math.round(crop.w),
328
+ height: Math.round(crop.h),
329
+ top: Math.round(crop.y),
330
+ left: Math.round(crop.x)
331
+ };
332
+ }
333
+ function toImage(src, params, meta) {
334
+ return __awaiter$w(this, void 0, void 0, function* () {
335
+ // Default params and meta
336
+ params = params || {};
337
+ meta = meta || {};
338
+ // Get default crop info
339
+ const crop = toCropRegion(meta.crop);
340
+ // Return the src if there are no params and no default crop exists
341
+ if (meta.extension === "svg" || (Object.keys(params).length == 0 && !crop)) {
342
+ return src;
343
+ }
344
+ // Parse params
345
+ params.rotation = isNaN(params.rotation) ? 0 : Math.round(params.rotation / 90) * 90;
346
+ params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : Number(params.canvasScaleX);
347
+ params.canvasScaleY = isNaN(params.canvasScaleY) ? 1 : Number(params.canvasScaleY);
348
+ params.scaleX = isNaN(params.scaleX) ? 1 : Number(params.scaleX);
349
+ params.scaleY = isNaN(params.scaleY) ? 1 : Number(params.scaleY);
350
+ params.crop = isBoolean(params.crop) ? params.crop : params.crop == "true";
351
+ let buffer = src instanceof Readable ? yield streamToBuffer(src) : src;
352
+ try {
353
+ // Get crop info
354
+ const cropBefore = toCropRegion(params.cropBefore || (params.crop ? meta.cropBefore : null));
355
+ const cropAfter = toCropRegion(params.cropAfter || (params.crop ? meta.cropAfter : null));
356
+ // Get metadata
357
+ let img = sharp$3(buffer);
358
+ let { width, height } = yield img.metadata();
359
+ // Crop before resize
360
+ if (cropBefore) {
361
+ width = cropBefore.width;
362
+ height = cropBefore.height;
363
+ img = img.extract(cropBefore);
364
+ }
365
+ else if (crop) {
366
+ width = crop.width;
367
+ height = crop.height;
368
+ img = img.extract(crop);
369
+ }
370
+ // Resize canvas
371
+ const canvasScaleX = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleX) || 1;
372
+ const canvasScaleY = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleY) || 1;
373
+ if (params.canvasScaleX !== canvasScaleX || params.canvasScaleY !== canvasScaleY) {
374
+ width = Math.round(width * params.canvasScaleX);
375
+ height = Math.round(height * params.canvasScaleY);
376
+ img = img.resize({ width, height, background: "#00000000", fit: "contain" });
377
+ }
378
+ // Resize image
379
+ if (params.scaleX !== 1 || params.scaleY !== 1) {
380
+ width = Math.round(width * params.scaleX);
381
+ height = Math.round(height * params.scaleY);
382
+ img = img.resize({ width, height, background: "#00000000", fit: "fill" });
383
+ }
384
+ // Crop after resize
385
+ if (cropAfter) {
386
+ img = img.extract(cropAfter);
387
+ }
388
+ // Rotate
389
+ if (params.rotation !== 0) {
390
+ buffer = yield img.toBuffer();
391
+ img = sharp$3(buffer).rotate(params.rotation);
392
+ }
393
+ buffer = yield img.toBuffer();
394
+ src = src instanceof Readable ? bufferToStream(buffer) : buffer;
395
+ return src;
396
+ }
397
+ catch (e) {
398
+ console.log("Image conversion error", e);
399
+ src = src instanceof Readable ? bufferToStream(buffer) : buffer;
400
+ return src;
401
+ }
402
+ });
403
+ }
304
404
  function bufferToStream(buffer) {
305
405
  const readStream = new PassThrough();
306
406
  readStream.end(buffer);
@@ -864,7 +964,7 @@ var __awaiter$v = (this && this.__awaiter) || function (thisArg, _arguments, P,
864
964
  });
865
965
  };
866
966
  var AssetProcessor_1;
867
- const sharp$3 = sharp_;
967
+ const sharp$2 = sharp_;
868
968
  const fontKit = fontKit_;
869
969
  const fontTypes = [
870
970
  "application/font-woff", "application/font-woff2", "application/x-font-opentype", "application/x-font-truetype", "application/x-font-datafork",
@@ -940,7 +1040,7 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
940
1040
  }
941
1041
  return buffer;
942
1042
  }
943
- const output = yield sharp$3(buffer).rotate().toBuffer({ resolveWithObject: true });
1043
+ const output = yield sharp$2(buffer).rotate().toBuffer({ resolveWithObject: true });
944
1044
  Object.assign(metadata, output.info);
945
1045
  return output.data;
946
1046
  });
@@ -1126,104 +1226,11 @@ var __awaiter$s = (this && this.__awaiter) || function (thisArg, _arguments, P,
1126
1226
  step((generator = generator.apply(thisArg, _arguments || [])).next());
1127
1227
  });
1128
1228
  };
1129
- const sharp$2 = sharp_;
1130
- const cropInterface = {
1131
- x: "number",
1132
- y: "number",
1133
- w: "number",
1134
- h: "number"
1135
- };
1136
1229
  class Asset extends BaseEntity {
1137
1230
  constructor(id, data, collection, bucket) {
1138
1231
  super(id, data, collection);
1139
1232
  this.bucket = bucket;
1140
1233
  }
1141
- static toCropRegion(cropInfo) {
1142
- let crop = cropInfo;
1143
- if (isString(cropInfo)) {
1144
- try {
1145
- crop = JSON.parse(cropInfo);
1146
- }
1147
- catch (e) {
1148
- return null;
1149
- }
1150
- }
1151
- if (!isInterface(crop, cropInterface))
1152
- return null;
1153
- return {
1154
- width: Math.round(crop.w),
1155
- height: Math.round(crop.h),
1156
- top: Math.round(crop.y),
1157
- left: Math.round(crop.x)
1158
- };
1159
- }
1160
- static toImage(stream, meta, params) {
1161
- return __awaiter$s(this, void 0, void 0, function* () {
1162
- params = params || {};
1163
- // Get default crop info
1164
- const crop = Asset.toCropRegion(meta.crop);
1165
- // Return the stream if there is no params and no default crop exists
1166
- if ((meta === null || meta === void 0 ? void 0 : meta.extension) === "svg" || (Object.keys(params).length == 0 && !crop)) {
1167
- return stream;
1168
- }
1169
- // Parse params
1170
- params.rotation = isNaN(params.rotation) ? 0 : Math.round(params.rotation / 90) * 90;
1171
- params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : Number(params.canvasScaleX);
1172
- params.canvasScaleY = isNaN(params.canvasScaleY) ? 1 : Number(params.canvasScaleY);
1173
- params.scaleX = isNaN(params.scaleX) ? 1 : Number(params.scaleX);
1174
- params.scaleY = isNaN(params.scaleY) ? 1 : Number(params.scaleY);
1175
- params.crop = isBoolean(params.crop) ? params.crop : params.crop == "true";
1176
- // Try to modify image
1177
- let buffer = yield streamToBuffer(stream);
1178
- try {
1179
- // Get crop info
1180
- const cropBefore = Asset.toCropRegion(params.cropBefore || (params.crop ? meta.cropBefore : null));
1181
- const cropAfter = Asset.toCropRegion(params.cropAfter || (params.crop ? meta.cropAfter : null));
1182
- // Get metadata
1183
- let img = sharp$2(buffer);
1184
- let { width, height } = yield img.metadata();
1185
- // Crop before resize
1186
- if (cropBefore) {
1187
- width = cropBefore.width;
1188
- height = cropBefore.height;
1189
- img = img.extract(cropBefore);
1190
- }
1191
- else if (crop) {
1192
- width = crop.width;
1193
- height = crop.height;
1194
- img = img.extract(crop);
1195
- }
1196
- // Resize canvas
1197
- const canvasScaleX = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleX) || 1;
1198
- const canvasScaleY = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleY) || 1;
1199
- if (params.canvasScaleX !== canvasScaleX || params.canvasScaleY !== canvasScaleY) {
1200
- width = Math.round(width * params.canvasScaleX);
1201
- height = Math.round(height * params.canvasScaleY);
1202
- img = img.resize({ width, height, background: "#00000000", fit: "contain" });
1203
- }
1204
- // Resize image
1205
- if (params.scaleX !== 1 || params.scaleY !== 1) {
1206
- width = Math.round(width * params.scaleX);
1207
- height = Math.round(height * params.scaleY);
1208
- img = img.resize({ width, height, background: "#00000000", fit: "fill" });
1209
- }
1210
- // Crop after resize
1211
- if (cropAfter) {
1212
- img = img.extract(cropAfter);
1213
- }
1214
- // Rotate
1215
- if (params.rotation !== 0) {
1216
- buffer = yield img.toBuffer();
1217
- img = sharp$2(buffer).rotate(params.rotation);
1218
- }
1219
- return bufferToStream(yield img.toBuffer());
1220
- }
1221
- catch (e) {
1222
- console.log("Asset image conversion error", e);
1223
- return bufferToStream(buffer);
1224
- }
1225
- });
1226
- }
1227
1234
  get filename() {
1228
1235
  return this.data.filename;
1229
1236
  }
@@ -1258,12 +1265,12 @@ class Asset extends BaseEntity {
1258
1265
  }
1259
1266
  getImage(params = null) {
1260
1267
  return __awaiter$s(this, void 0, void 0, function* () {
1261
- return Asset.toImage(this.stream, this.metadata, params);
1268
+ return toImage(this.stream, params, this.metadata);
1262
1269
  });
1263
1270
  }
1264
1271
  downloadImage(params, metadata) {
1265
1272
  return __awaiter$s(this, void 0, void 0, function* () {
1266
- return Asset.toImage(yield this.download(metadata), this.metadata, params);
1273
+ return toImage(yield this.download(metadata), params, this.metadata);
1267
1274
  });
1268
1275
  }
1269
1276
  }
@@ -1305,7 +1312,7 @@ class TempAsset {
1305
1312
  }
1306
1313
  downloadImage(params, metadata) {
1307
1314
  Object.assign(this.metadata, metadata || {});
1308
- return Asset.toImage(this.stream, this.metadata, params);
1315
+ return toImage(this.stream, params, this.metadata);
1309
1316
  }
1310
1317
  getImage(params) {
1311
1318
  return this.downloadImage(params);
@@ -1442,6 +1449,12 @@ let Assets = class Assets {
1442
1449
  return result;
1443
1450
  });
1444
1451
  }
1452
+ deleteMany(where) {
1453
+ return __awaiter$q(this, void 0, void 0, function* () {
1454
+ const assets = yield this.findMany(where);
1455
+ return Promise.all(assets.map(a => a.unlink()));
1456
+ });
1457
+ }
1445
1458
  unlink(id) {
1446
1459
  return __awaiter$q(this, void 0, void 0, function* () {
1447
1460
  const asset = yield this.read(id);
@@ -3130,6 +3143,12 @@ let AssetsController = class AssetsController {
3130
3143
  }
3131
3144
  });
3132
3145
  }
3146
+ getFile(id, lazy, res) {
3147
+ return __awaiter$7(this, void 0, void 0, function* () {
3148
+ const asset = yield this.getAsset("Asset", id, lazy, res);
3149
+ return asset.download();
3150
+ });
3151
+ }
3133
3152
  getImageRotation(id, params, res, rotation = 0) {
3134
3153
  return __awaiter$7(this, void 0, void 0, function* () {
3135
3154
  const asset = yield this.getAsset("Image", id, params.lazy, res);
@@ -3144,29 +3163,48 @@ let AssetsController = class AssetsController {
3144
3163
  return this.getImageRotation(id, params, res);
3145
3164
  });
3146
3165
  }
3147
- getFile(id, lazy, res) {
3166
+ getFileByName(name, res) {
3148
3167
  return __awaiter$7(this, void 0, void 0, function* () {
3149
- const asset = yield this.getAsset("Asset", id, lazy, res);
3168
+ const asset = yield this.getAssetByName("Asset", name, res);
3150
3169
  return asset.download();
3151
3170
  });
3152
3171
  }
3153
- getAsset(type, id, lazy, res) {
3172
+ getImageByName(name, params, res) {
3173
+ return __awaiter$7(this, void 0, void 0, function* () {
3174
+ const asset = yield this.getAssetByName("Image", name, res);
3175
+ return asset.downloadImage(params);
3176
+ });
3177
+ }
3178
+ setAssetHeaders(type, asset, res) {
3154
3179
  var _a, _b;
3180
+ if ((_a = asset.metadata) === null || _a === void 0 ? void 0 : _a.classified) {
3181
+ throw new HttpError(403, `${type} is classified, and can be only downloaded from a custom url.`);
3182
+ }
3183
+ const ext = (_b = asset.metadata) === null || _b === void 0 ? void 0 : _b.extension;
3184
+ if (ext) {
3185
+ res.header("content-disposition", `inline; filename=${asset.filename}.${ext}`);
3186
+ }
3187
+ if (asset.contentType) {
3188
+ res.header("content-type", asset.contentType);
3189
+ }
3190
+ }
3191
+ getAsset(type, id, lazy, res) {
3155
3192
  return __awaiter$7(this, void 0, void 0, function* () {
3156
3193
  const asset = yield this.assetResolver.resolve(id, lazy);
3157
3194
  if (!asset) {
3158
3195
  throw new HttpError(404, `${type} with id: '${id}' not found.`);
3159
3196
  }
3160
- if ((_a = asset.metadata) === null || _a === void 0 ? void 0 : _a.classified) {
3161
- throw new HttpError(403, `${type} is classified, and can be only downloaded from a custom url.`);
3162
- }
3163
- const ext = (_b = asset.metadata) === null || _b === void 0 ? void 0 : _b.extension;
3164
- if (ext) {
3165
- res.header("content-disposition", `inline; filename=${asset.filename}.${ext}`);
3166
- }
3167
- if (asset.contentType) {
3168
- res.header("content-type", asset.contentType);
3197
+ this.setAssetHeaders(type, asset, res);
3198
+ return asset;
3199
+ });
3200
+ }
3201
+ getAssetByName(type, filename, res) {
3202
+ return __awaiter$7(this, void 0, void 0, function* () {
3203
+ const asset = yield this.assets.find({ filename });
3204
+ if (!asset) {
3205
+ throw new HttpError(404, `${type} with filename: '${filename}' not found.`);
3169
3206
  }
3207
+ this.setAssetHeaders(type, asset, res);
3170
3208
  return asset;
3171
3209
  });
3172
3210
  }
@@ -3187,6 +3225,13 @@ __decorate$a([
3187
3225
  __metadata$7("design:paramtypes", [Object]),
3188
3226
  __metadata$7("design:returntype", Promise)
3189
3227
  ], AssetsController.prototype, "uploadUrl", null);
3228
+ __decorate$a([
3229
+ Get("/:id"),
3230
+ __param$5(0, Param("id")), __param$5(1, QueryParam("lazy")), __param$5(2, Res()),
3231
+ __metadata$7("design:type", Function),
3232
+ __metadata$7("design:paramtypes", [String, Boolean, Object]),
3233
+ __metadata$7("design:returntype", Promise)
3234
+ ], AssetsController.prototype, "getFile", null);
3190
3235
  __decorate$a([
3191
3236
  Get("/image/:id/:rotation"),
3192
3237
  __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Res()), __param$5(3, Param("rotation")),
@@ -3202,12 +3247,19 @@ __decorate$a([
3202
3247
  __metadata$7("design:returntype", Promise)
3203
3248
  ], AssetsController.prototype, "getImage", null);
3204
3249
  __decorate$a([
3205
- Get("/:id"),
3206
- __param$5(0, Param("id")), __param$5(1, QueryParam("lazy")), __param$5(2, Res()),
3250
+ Get("/by-name/:name"),
3251
+ __param$5(0, Param("name")), __param$5(1, Res()),
3207
3252
  __metadata$7("design:type", Function),
3208
- __metadata$7("design:paramtypes", [String, Boolean, Object]),
3253
+ __metadata$7("design:paramtypes", [String, Object]),
3209
3254
  __metadata$7("design:returntype", Promise)
3210
- ], AssetsController.prototype, "getFile", null);
3255
+ ], AssetsController.prototype, "getFileByName", null);
3256
+ __decorate$a([
3257
+ Get("/by-name/image/:name"),
3258
+ __param$5(0, Param("name")), __param$5(1, QueryParams()), __param$5(2, Res()),
3259
+ __metadata$7("design:type", Function),
3260
+ __metadata$7("design:paramtypes", [String, Object, Object]),
3261
+ __metadata$7("design:returntype", Promise)
3262
+ ], AssetsController.prototype, "getImageByName", null);
3211
3263
  AssetsController = __decorate$a([
3212
3264
  injectable(),
3213
3265
  Controller("/assets"),
@@ -4159,5 +4211,5 @@ function setupBackend(config, providers, parent) {
4159
4211
  * Generated bundle index. Do not edit.
4160
4212
  */
4161
4213
 
4162
- export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, ConsoleColor, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, colorize, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isPrimitive, isString, isType, jsonHighlight, lastItem, lcFirst, letsLookupStage, lookupStages, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, regroup, replaceSpecialChars, runCommand, setupBackend, streamToBuffer, ucFirst, uniqueItems, valueToPromise, writeFile };
4214
+ export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, ConsoleColor, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, colorize, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isObjectId, isPrimitive, isString, isType, jsonHighlight, lastItem, lcFirst, letsLookupStage, lookupStages, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, regroup, replaceSpecialChars, runCommand, setupBackend, streamToBuffer, toImage, ucFirst, uniqueItems, valueToPromise, writeFile };
4163
4215
  //# sourceMappingURL=stemy-backend.js.map