@stemy/backend 2.8.4 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, QueryParam, Res, Controller, CurrentUser, Middleware, useContainer, useExpressServer } from 'routing-controllers';
5
+ import { createParamDecorator, BadRequestError, HttpError, getMetadataArgsStorage, Authorized, Post, UploadedFile, Body, Get, Param, QueryParams, Res, QueryParam, 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';
@@ -18,7 +18,7 @@ import { getValue as getValue$1, setValue } from 'mongoose/lib/utils';
18
18
  import { PassThrough, Readable } from 'stream';
19
19
  import { ObjectId } from 'bson';
20
20
  import fontKit_ from 'fontkit';
21
- import { fromBuffer, fromStream } from 'file-type';
21
+ import { fromBuffer } from 'file-type';
22
22
  import sharp_ from 'sharp';
23
23
  import axios from 'axios';
24
24
  import { GridFSBucket } from 'mongodb';
@@ -774,18 +774,24 @@ const fontProps = [
774
774
  "xHeight", "numGlyphs", "characterSet", "availableFeatures"
775
775
  ];
776
776
  let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
777
- static getMimeType(buffer, mimeType) {
777
+ static checkTextFileType(type) {
778
+ return type.mime.indexOf("text") >= 0 || type.mime.indexOf("xml") >= 0;
779
+ }
780
+ static fixTextFileType(type, buffer) {
781
+ const text = buffer.toString("utf8");
782
+ if (text.indexOf("<svg") >= 0) {
783
+ return { ext: "svg", mime: "image/svg+xml" };
784
+ }
785
+ return type;
786
+ }
787
+ static fileTypeFromBuffer(buffer) {
788
+ var _a;
778
789
  return __awaiter$u(this, void 0, void 0, function* () {
779
- try {
780
- mimeType = (yield fromBuffer(buffer)).mime;
790
+ const type = ((_a = yield fromBuffer(buffer)) !== null && _a !== void 0 ? _a : { ext: "txt", mime: "text/plain" });
791
+ if (AssetProcessor_1.checkTextFileType(type)) {
792
+ return AssetProcessor_1.fixTextFileType(type, buffer);
781
793
  }
782
- catch (e) {
783
- if (!mimeType) {
784
- throw `Can't determine mime type`;
785
- }
786
- console.log(`Can't determine mime type`, e);
787
- }
788
- return mimeType;
794
+ return type;
789
795
  });
790
796
  }
791
797
  static extractFontFormat(font) {
@@ -823,12 +829,12 @@ let AssetProcessor = AssetProcessor_1 = class AssetProcessor {
823
829
  metadata[prop] = font[prop];
824
830
  });
825
831
  }
826
- process(buffer, metadata, contentType) {
832
+ process(buffer, metadata, fileType) {
827
833
  return __awaiter$u(this, void 0, void 0, function* () {
828
- if (AssetProcessor_1.isImage(contentType)) {
834
+ if (AssetProcessor_1.isImage(fileType.mime)) {
829
835
  buffer = yield AssetProcessor_1.copyImageMeta(buffer, metadata);
830
836
  }
831
- if (AssetProcessor_1.isFont(contentType)) {
837
+ if (AssetProcessor_1.isFont(fileType.mime)) {
832
838
  AssetProcessor_1.copyFontMeta(buffer, metadata);
833
839
  }
834
840
  return buffer;
@@ -1171,56 +1177,37 @@ let Assets = class Assets {
1171
1177
  }
1172
1178
  write(stream, contentType = null, metadata = null) {
1173
1179
  return __awaiter$q(this, void 0, void 0, function* () {
1174
- let extension = null;
1175
- const fileTypeStream = copyStream(stream);
1176
1180
  const uploadStream = copyStream(stream);
1181
+ const buffer = yield streamToBuffer(stream);
1182
+ let fileType = { ext: "", mime: contentType };
1177
1183
  try {
1178
- const fileType = yield fromStream(fileTypeStream);
1179
- contentType = fileType.mime;
1180
- extension = fileType.ext;
1184
+ fileType = yield AssetProcessor.fileTypeFromBuffer(buffer);
1181
1185
  }
1182
1186
  catch (e) {
1183
- if (!contentType) {
1184
- throw `Can't determine content type`;
1187
+ if (!fileType.mime) {
1188
+ throw `Can't determine mime type`;
1185
1189
  }
1186
- console.log(`Can't determine content type`, e);
1190
+ console.log(`Can't determine mime type`, e);
1187
1191
  }
1188
- contentType = contentType.trim();
1189
- extension = (extension || "").trim();
1190
- metadata = Object.assign({
1191
- extension,
1192
- downloadCount: 0,
1193
- firstDownload: null,
1194
- lastDownload: null
1195
- }, metadata || {});
1196
- metadata.filename = metadata.filename || new ObjectId().toHexString();
1197
- return new Promise(((resolve, reject) => {
1198
- const uploaderStream = this.bucket.openUploadStream(metadata.filename);
1199
- uploadStream.pipe(uploaderStream)
1200
- .on("error", error => {
1201
- reject(error.message || error);
1202
- })
1203
- .on("finish", () => {
1204
- const asset = new Asset(uploaderStream.id, {
1205
- filename: metadata.filename,
1206
- contentType,
1207
- metadata
1208
- }, this.collection, this.bucket);
1209
- asset.save().then(() => {
1210
- resolve(asset);
1211
- }, error => {
1212
- reject(error.message || error);
1213
- });
1214
- });
1215
- }));
1192
+ metadata = metadata || {};
1193
+ return this.upload(uploadStream, fileType, metadata);
1216
1194
  });
1217
1195
  }
1218
1196
  writeBuffer(buffer, metadata = null, contentType = null) {
1219
1197
  return __awaiter$q(this, void 0, void 0, function* () {
1220
- contentType = yield AssetProcessor.getMimeType(buffer, contentType);
1198
+ let fileType = { ext: "", mime: contentType };
1199
+ try {
1200
+ fileType = yield AssetProcessor.fileTypeFromBuffer(buffer);
1201
+ }
1202
+ catch (e) {
1203
+ if (!fileType.mime) {
1204
+ throw `Can't determine mime type`;
1205
+ }
1206
+ console.log(`Can't determine mime type`, e);
1207
+ }
1221
1208
  metadata = metadata || {};
1222
- buffer = yield this.assetProcessor.process(buffer, metadata, contentType);
1223
- return this.write(bufferToStream(buffer), contentType, metadata);
1209
+ buffer = yield this.assetProcessor.process(buffer, metadata, fileType);
1210
+ return this.upload(bufferToStream(buffer), fileType, metadata);
1224
1211
  });
1225
1212
  }
1226
1213
  writeUrl(url, metadata = null) {
@@ -1231,7 +1218,7 @@ let Assets = class Assets {
1231
1218
  }
1232
1219
  read(id) {
1233
1220
  return __awaiter$q(this, void 0, void 0, function* () {
1234
- return this.find({ _id: new ObjectId(id) });
1221
+ return !id ? null : this.find({ _id: new ObjectId(id) });
1235
1222
  });
1236
1223
  }
1237
1224
  find(where) {
@@ -1261,6 +1248,38 @@ let Assets = class Assets {
1261
1248
  return asset.unlink();
1262
1249
  });
1263
1250
  }
1251
+ upload(stream, fileType, metadata) {
1252
+ return __awaiter$q(this, void 0, void 0, function* () {
1253
+ const contentType = fileType.mime.trim();
1254
+ const extension = (fileType.ext || "").trim();
1255
+ metadata = Object.assign({
1256
+ extension,
1257
+ downloadCount: 0,
1258
+ firstDownload: null,
1259
+ lastDownload: null
1260
+ }, metadata || {});
1261
+ metadata.filename = metadata.filename || new ObjectId().toHexString();
1262
+ return new Promise(((resolve, reject) => {
1263
+ const uploaderStream = this.bucket.openUploadStream(metadata.filename);
1264
+ stream.pipe(uploaderStream)
1265
+ .on("error", error => {
1266
+ reject(error.message || error);
1267
+ })
1268
+ .on("finish", () => {
1269
+ const asset = new Asset(uploaderStream.id, {
1270
+ filename: metadata.filename,
1271
+ contentType,
1272
+ metadata
1273
+ }, this.collection, this.bucket);
1274
+ asset.save().then(() => {
1275
+ resolve(asset);
1276
+ }, error => {
1277
+ reject(error.message || error);
1278
+ });
1279
+ });
1280
+ }));
1281
+ });
1282
+ }
1264
1283
  };
1265
1284
  Assets = __decorate$t([
1266
1285
  injectable(),
@@ -1312,13 +1331,13 @@ class LazyAsset extends BaseEntity {
1312
1331
  this.load().then(() => {
1313
1332
  if (this.deleted)
1314
1333
  return;
1315
- const progressPromise = !this.progressId ? Promise.resolve(null) : this.progresses.get(this.progressId).then(p => p.cancel());
1316
- progressPromise.then(() => {
1317
- this.startWorkingOnAsset().then(() => {
1318
- console.log(`Started working on lazy asset: ${this.id}`);
1319
- }).catch(reason => {
1320
- console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1321
- });
1334
+ this.progresses.get(this.progressId).then(p => {
1335
+ p === null || p === void 0 ? void 0 : p.cancel();
1336
+ });
1337
+ this.startWorkingOnAsset().then(() => {
1338
+ console.log(`Started working on lazy asset: ${this.id}`);
1339
+ }).catch(reason => {
1340
+ console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
1322
1341
  });
1323
1342
  });
1324
1343
  }
@@ -1797,7 +1816,7 @@ let Progresses = class Progresses {
1797
1816
  }
1798
1817
  get(id) {
1799
1818
  return __awaiter$m(this, void 0, void 0, function* () {
1800
- return this.find({ _id: new ObjectId(id) });
1819
+ return !id ? null : this.find({ _id: new ObjectId(id) });
1801
1820
  });
1802
1821
  }
1803
1822
  find(where) {
@@ -1878,7 +1897,7 @@ let LazyAssets = class LazyAssets {
1878
1897
  }
1879
1898
  read(id) {
1880
1899
  return __awaiter$l(this, void 0, void 0, function* () {
1881
- return this.find({ _id: new ObjectId(id) });
1900
+ return !id ? null : this.find({ _id: new ObjectId(id) });
1882
1901
  });
1883
1902
  }
1884
1903
  find(where) {
@@ -2860,40 +2879,42 @@ let AssetsController = class AssetsController {
2860
2879
  }
2861
2880
  });
2862
2881
  }
2863
- getImageRotation(id, params, rotation = 0) {
2864
- var _a;
2882
+ getImageRotation(id, params, res, rotation = 0) {
2865
2883
  return __awaiter$7(this, void 0, void 0, function* () {
2866
- const asset = yield this.assetResolver.resolve(id, params.lazy);
2867
- if (!asset) {
2868
- throw new HttpError(404, `Image with id: '${id}' not found.`);
2869
- }
2870
- if ((_a = asset.metadata) === null || _a === void 0 ? void 0 : _a.classified) {
2871
- throw new HttpError(403, `Image is classified, and can be only downloaded from a custom url.`);
2872
- }
2884
+ const asset = yield this.getAsset("Asset", id, params.lazy, res);
2873
2885
  params.rotation = params.rotation || rotation;
2874
2886
  return asset.downloadImage(params);
2875
2887
  });
2876
2888
  }
2877
- getImage(id, params) {
2889
+ getImage(id, params, res) {
2878
2890
  return __awaiter$7(this, void 0, void 0, function* () {
2879
- return this.getImageRotation(id, params);
2891
+ return this.getImageRotation(id, params, res);
2880
2892
  });
2881
2893
  }
2882
2894
  getFile(id, lazy, res) {
2895
+ return __awaiter$7(this, void 0, void 0, function* () {
2896
+ const asset = yield this.getAsset("Asset", id, lazy, res);
2897
+ return asset.download();
2898
+ });
2899
+ }
2900
+ getAsset(type, id, lazy, res) {
2883
2901
  var _a, _b;
2884
2902
  return __awaiter$7(this, void 0, void 0, function* () {
2885
2903
  const asset = yield this.assetResolver.resolve(id, lazy);
2886
2904
  if (!asset) {
2887
- throw new HttpError(404, `File with id: '${id}' not found.`);
2905
+ throw new HttpError(404, `${type} with id: '${id}' not found.`);
2888
2906
  }
2889
2907
  if ((_a = asset.metadata) === null || _a === void 0 ? void 0 : _a.classified) {
2890
- throw new HttpError(403, `Asset is classified, and can be only downloaded from a custom url.`);
2908
+ throw new HttpError(403, `${type} is classified, and can be only downloaded from a custom url.`);
2891
2909
  }
2892
2910
  const ext = (_b = asset.metadata) === null || _b === void 0 ? void 0 : _b.extension;
2893
2911
  if (ext) {
2894
2912
  res.header("content-disposition", `inline; filename=${asset.filename}.${ext}`);
2895
2913
  }
2896
- return asset.download();
2914
+ if (asset.contentType) {
2915
+ res.header("content-type", asset.contentType);
2916
+ }
2917
+ return asset;
2897
2918
  });
2898
2919
  }
2899
2920
  };
@@ -2915,16 +2936,16 @@ __decorate$a([
2915
2936
  ], AssetsController.prototype, "uploadUrl", null);
2916
2937
  __decorate$a([
2917
2938
  Get("/image/:id/:rotation"),
2918
- __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Param("rotation")),
2939
+ __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Res()), __param$5(3, Param("rotation")),
2919
2940
  __metadata$7("design:type", Function),
2920
- __metadata$7("design:paramtypes", [String, Object, Number]),
2941
+ __metadata$7("design:paramtypes", [String, Object, Object, Number]),
2921
2942
  __metadata$7("design:returntype", Promise)
2922
2943
  ], AssetsController.prototype, "getImageRotation", null);
2923
2944
  __decorate$a([
2924
2945
  Get("/image/:id"),
2925
- __param$5(0, Param("id")), __param$5(1, QueryParams()),
2946
+ __param$5(0, Param("id")), __param$5(1, QueryParams()), __param$5(2, Res()),
2926
2947
  __metadata$7("design:type", Function),
2927
- __metadata$7("design:paramtypes", [String, Object]),
2948
+ __metadata$7("design:paramtypes", [String, Object, Object]),
2928
2949
  __metadata$7("design:returntype", Promise)
2929
2950
  ], AssetsController.prototype, "getImage", null);
2930
2951
  __decorate$a([