@stemy/backend 5.1.1 → 5.2.0

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.
@@ -15,7 +15,7 @@ import { exec } from 'child_process';
15
15
  import { createHash } from 'crypto';
16
16
  import { Subscription, Observable, Subject, from, BehaviorSubject } from 'rxjs';
17
17
  import { canReportError } from 'rxjs/internal/util/canReportError';
18
- import { ObjectId, GridFSBucket } from 'mongodb';
18
+ import { ObjectId } from 'mongodb';
19
19
  import mongoose from 'mongoose';
20
20
  import { Readable, PassThrough } from 'stream';
21
21
  import fileType from 'file-type/core';
@@ -37,6 +37,7 @@ import * as Handlebars from 'handlebars';
37
37
  import { CommandsAddon, AnsiCodes } from '@stemy/terminal-commands-addon';
38
38
  import { compare } from 'bcrypt';
39
39
  import moment from 'moment';
40
+ import { GridFSBucket } from 'mongodb/lib/gridfs';
40
41
  import { getModelForClass } from '@typegoose/typegoose';
41
42
  import { getValue as getValue$1, setValue } from 'mongoose/lib/utils';
42
43
 
@@ -53,6 +54,8 @@ const SOCKET_CONTROLLERS = Symbol.for("socket-controllers-token");
53
54
  const PARAMETER = Symbol.for("parameter-token");
54
55
  const DI_CONTAINER = Symbol.for("di-container-token");
55
56
  const OPENAPI_VALIDATION = Symbol.for("openapi-validation-token");
57
+ const LOCAL_DIR = Symbol.for('asset-local-dir');
58
+ const ASSET_DRIVER = Symbol.for('assets-driver');
56
59
  class Parameter {
57
60
  constructor(name, defaultValue, resolver = null) {
58
61
  this.name = name;
@@ -931,14 +934,10 @@ let MongoConnector = class MongoConnector {
931
934
  get database() {
932
935
  return this.db;
933
936
  }
934
- get bucket() {
935
- return this.fsBucket;
936
- }
937
937
  constructor(configuration) {
938
938
  this.configuration = configuration;
939
939
  this.conn = null;
940
940
  this.db = null;
941
- this.fsBucket = null;
942
941
  }
943
942
  async connect() {
944
943
  if (this.db)
@@ -949,7 +948,6 @@ let MongoConnector = class MongoConnector {
949
948
  pass: this.configuration.resolve("mongoPassword")
950
949
  })).connection;
951
950
  this.db = this.conn.db;
952
- this.fsBucket = new GridFSBucket(this.db, { bucketName: "assets" });
953
951
  }
954
952
  };
955
953
  MongoConnector = __decorate([
@@ -959,18 +957,18 @@ MongoConnector = __decorate([
959
957
 
960
958
  class BaseEntity {
961
959
  get id() {
962
- return this.mId.toHexString();
960
+ return this.oid.toHexString();
963
961
  }
964
- constructor(mId, data, collection) {
965
- this.mId = mId;
962
+ constructor(oid, data, collection) {
963
+ this.oid = oid;
966
964
  this.data = data;
967
965
  this.collection = collection;
968
966
  }
969
967
  save() {
970
- return this.collection.updateOne({ _id: this.mId }, { $set: this.toJSON() });
968
+ return this.collection.updateOne({ _id: this.oid }, { $set: this.toJSON() }, { upsert: true });
971
969
  }
972
970
  async load() {
973
- const res = await this.collection.findOne({ _id: this.mId });
971
+ const res = await this.collection.findOne({ _id: this.oid });
974
972
  this.deleted = !res;
975
973
  this.data = res || {};
976
974
  return this;
@@ -996,18 +994,31 @@ class Asset extends BaseEntity {
996
994
  return this.data.metadata;
997
995
  }
998
996
  get stream() {
999
- return this.bucket.openDownloadStream(this.mId);
997
+ return this.driver.openDownloadStream(this.oid);
1000
998
  }
1001
- constructor(id, data, collection, bucket) {
999
+ constructor(id, data, collection, driver) {
1002
1000
  super(id, data, collection);
1003
- this.bucket = bucket;
1001
+ this.driver = driver;
1004
1002
  }
1005
1003
  async unlink() {
1006
- return deleteFromBucket(this.bucket, this.mId);
1004
+ try {
1005
+ await this.driver.delete(this.oid);
1006
+ await this.collection.deleteOne({ _id: this.oid });
1007
+ }
1008
+ catch (error) {
1009
+ let err = error;
1010
+ if (error) {
1011
+ err = error.message || error || "";
1012
+ if (!isString(err) || !err.startsWith("FileNotFound")) {
1013
+ throw err;
1014
+ }
1015
+ }
1016
+ }
1017
+ return this.id;
1007
1018
  }
1008
1019
  async setMeta(metadata) {
1009
1020
  metadata = Object.assign(this.metadata, metadata || {});
1010
- await this.collection.updateOne({ _id: this.mId }, { $set: { metadata } });
1021
+ await this.collection.updateOne({ _id: this.oid }, { $set: { metadata } });
1011
1022
  }
1012
1023
  getBuffer() {
1013
1024
  return streamToBuffer(this.stream);
@@ -1019,7 +1030,7 @@ class Asset extends BaseEntity {
1019
1030
  : metadata.downloadCount + 1;
1020
1031
  metadata.firstDownload = metadata.firstDownload || new Date();
1021
1032
  metadata.lastDownload = new Date();
1022
- await this.collection.updateOne({ _id: this.mId }, { $set: { metadata } });
1033
+ await this.collection.updateOne({ _id: this.oid }, { $set: { metadata } });
1023
1034
  return this.stream;
1024
1035
  }
1025
1036
  async getImage(params = null) {
@@ -1077,11 +1088,11 @@ class TempAsset {
1077
1088
  }
1078
1089
 
1079
1090
  let Assets = class Assets {
1080
- constructor(connector, assetProcessor) {
1091
+ constructor(connector, assetProcessor, driver) {
1081
1092
  this.connector = connector;
1082
1093
  this.assetProcessor = assetProcessor;
1083
- this.bucket = connector.bucket;
1084
- this.collection = connector.database?.collection("assets.files");
1094
+ this.driver = driver;
1095
+ this.collection = connector.database?.collection(driver.metaCollection);
1085
1096
  }
1086
1097
  async write(stream, contentType = null, metadata = null) {
1087
1098
  const uploadStream = copyStream(stream);
@@ -1150,7 +1161,7 @@ let Assets = class Assets {
1150
1161
  }
1151
1162
  async find(where) {
1152
1163
  const data = await this.collection.findOne(where);
1153
- return !data ? null : new Asset(data._id, data, this.collection, this.bucket);
1164
+ return !data ? null : new Asset(data._id, data, this.collection, this.driver);
1154
1165
  }
1155
1166
  async findMany(where) {
1156
1167
  const cursor = this.collection.find(where);
@@ -1159,7 +1170,7 @@ let Assets = class Assets {
1159
1170
  for (let item of items) {
1160
1171
  if (!item)
1161
1172
  continue;
1162
- result.push(new Asset(item._id, item, this.collection, this.bucket));
1173
+ result.push(new Asset(item._id, item, this.collection, this.driver));
1163
1174
  }
1164
1175
  return result;
1165
1176
  }
@@ -1183,7 +1194,11 @@ let Assets = class Assets {
1183
1194
  metadata.filename = metadata.filename || new ObjectId$1().toHexString();
1184
1195
  metadata.extension = (fileType.ext || "").trim();
1185
1196
  return new Promise(((resolve, reject) => {
1186
- const uploaderStream = this.bucket.openUploadStream(metadata.filename);
1197
+ const uploaderStream = this.driver.openUploadStream(metadata.filename, {
1198
+ chunkSizeBytes: 1048576,
1199
+ metadata,
1200
+ contentType: fileType.mime
1201
+ });
1187
1202
  stream.pipe(uploaderStream)
1188
1203
  .on("error", error => {
1189
1204
  reject(error.message || error);
@@ -1193,7 +1208,7 @@ let Assets = class Assets {
1193
1208
  filename: metadata.filename,
1194
1209
  contentType,
1195
1210
  metadata
1196
- }, this.collection, this.bucket);
1211
+ }, this.collection, this.driver);
1197
1212
  asset.save().then(() => {
1198
1213
  resolve(asset);
1199
1214
  }, error => {
@@ -1206,7 +1221,9 @@ let Assets = class Assets {
1206
1221
  Assets = __decorate([
1207
1222
  injectable(),
1208
1223
  scoped(Lifecycle.ContainerScoped),
1209
- __metadata("design:paramtypes", [MongoConnector, AssetProcessor])
1224
+ __param(2, inject(ASSET_DRIVER)),
1225
+ __metadata("design:paramtypes", [MongoConnector,
1226
+ AssetProcessor, Object])
1210
1227
  ], Assets);
1211
1228
 
1212
1229
  class LazyAsset extends BaseEntity {
@@ -1240,9 +1257,9 @@ class LazyAsset extends BaseEntity {
1240
1257
  async unlink() {
1241
1258
  await this.load();
1242
1259
  if (!this.progressId) {
1243
- await this.collection.deleteOne({ _id: this.mId });
1260
+ await this.collection.deleteOne({ _id: this.oid });
1244
1261
  }
1245
- return deleteFromBucket(this.assets.bucket, new ObjectId$1(this.assetId));
1262
+ return this.assets.unlink(this.assetId);
1246
1263
  }
1247
1264
  startWorking() {
1248
1265
  this.load().then(() => {
@@ -1285,7 +1302,7 @@ class LazyAsset extends BaseEntity {
1285
1302
  this.data.progressId = (await this.progresses.create()).id;
1286
1303
  this.data.assetId = null;
1287
1304
  await this.save();
1288
- await deleteFromBucket(this.assets.bucket, oldAsset);
1305
+ await this.assets.unlink(oldAsset);
1289
1306
  const jobParams = JSON.parse(await gunzipPromised(this.data.jobParams));
1290
1307
  await this.progresses.jobMan.enqueueWithName(this.data.jobName, { ...jobParams, lazyId: this.id, fromLoad });
1291
1308
  }
@@ -3843,6 +3860,26 @@ const fixtures = [
3843
3860
  TtlFixture,
3844
3861
  ];
3845
3862
 
3863
+ let AssetGridDriver = class AssetGridDriver {
3864
+ constructor(connector) {
3865
+ this.bucket = new GridFSBucket(connector.database, { bucketName: 'assets' });
3866
+ this.metaCollection = "assets.files";
3867
+ }
3868
+ openUploadStream(filename, opts) {
3869
+ return this.bucket.openUploadStream(filename, opts);
3870
+ }
3871
+ openDownloadStream(id) {
3872
+ return this.bucket.openDownloadStream(id);
3873
+ }
3874
+ delete(id) {
3875
+ return this.bucket.delete(id);
3876
+ }
3877
+ };
3878
+ AssetGridDriver = __decorate([
3879
+ injectable(),
3880
+ __metadata("design:paramtypes", [MongoConnector])
3881
+ ], AssetGridDriver);
3882
+
3846
3883
  class BaseDoc {
3847
3884
  /**
3848
3885
  * Casts this to DocumentType<this> to allow using document methods in get/set-s
@@ -4373,6 +4410,12 @@ async function setupBackend(config, providers, parent) {
4373
4410
  diContainer.register(OPENAPI_VALIDATION, {
4374
4411
  useValue: config.customValidation || (() => null)
4375
4412
  });
4413
+ diContainer.register(LOCAL_DIR, {
4414
+ useValue: config.assetLocalDir || "assets_files"
4415
+ });
4416
+ diContainer.register(ASSET_DRIVER, {
4417
+ useClass: config.assetDriver || AssetGridDriver
4418
+ });
4376
4419
  diContainers.appContainer = diContainers.appContainer || diContainer;
4377
4420
  // Authentication
4378
4421
  restOptions.authorizationChecker = async (action, roles) => {