@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.
- package/bundles/stemy-backend.umd.js +143 -106
- package/bundles/stemy-backend.umd.js.map +1 -1
- package/bundles/stemy-backend.umd.min.js +1 -1
- package/bundles/stemy-backend.umd.min.js.map +1 -1
- package/common-types.d.ts +4 -0
- package/esm2015/common-types.js +1 -1
- package/esm2015/public_api.js +1 -1
- package/esm2015/rest-controllers/assets.controller.js +21 -19
- package/esm2015/services/asset-processor.js +20 -14
- package/esm2015/services/assets.js +55 -43
- package/esm2015/services/entities/lazy-asset.js +8 -8
- package/esm2015/services/lazy-assets.js +2 -2
- package/esm2015/services/progresses.js +2 -2
- package/fesm2015/stemy-backend.js +103 -82
- package/fesm2015/stemy-backend.js.map +1 -1
- package/package.json +1 -6
- package/public_api.d.ts +1 -1
- package/rest-controllers/assets.controller.d.ts +4 -3
- package/services/asset-processor.d.ts +5 -3
- package/services/assets.d.ts +2 -1
- package/stemy-backend.metadata.json +1 -1
|
@@ -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,
|
|
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
|
|
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
|
|
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
|
-
|
|
780
|
-
|
|
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
|
-
|
|
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,
|
|
832
|
+
process(buffer, metadata, fileType) {
|
|
827
833
|
return __awaiter$u(this, void 0, void 0, function* () {
|
|
828
|
-
if (AssetProcessor_1.isImage(
|
|
834
|
+
if (AssetProcessor_1.isImage(fileType.mime)) {
|
|
829
835
|
buffer = yield AssetProcessor_1.copyImageMeta(buffer, metadata);
|
|
830
836
|
}
|
|
831
|
-
if (AssetProcessor_1.isFont(
|
|
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
|
-
|
|
1179
|
-
contentType = fileType.mime;
|
|
1180
|
-
extension = fileType.ext;
|
|
1184
|
+
fileType = yield AssetProcessor.fileTypeFromBuffer(buffer);
|
|
1181
1185
|
}
|
|
1182
1186
|
catch (e) {
|
|
1183
|
-
if (!
|
|
1184
|
-
throw `Can't determine
|
|
1187
|
+
if (!fileType.mime) {
|
|
1188
|
+
throw `Can't determine mime type`;
|
|
1185
1189
|
}
|
|
1186
|
-
console.log(`Can't determine
|
|
1190
|
+
console.log(`Can't determine mime type`, e);
|
|
1187
1191
|
}
|
|
1188
|
-
|
|
1189
|
-
|
|
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
|
-
|
|
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,
|
|
1223
|
-
return this.
|
|
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
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
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.
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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([
|