lynx-framework
Version:
lynx is a NodeJS framework for Web Development, based on decorators and the async/await support.
456 lines (454 loc) • 31.7 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var typeorm_1 = require("typeorm");
var base_entity_1 = require("./base.entity");
var user_entity_1 = require("./user.entity");
var Jimp = require("jimp");
var uuid_1 = require("uuid");
var uuid = uuid_1.v4;
var app_1 = require("../app");
var fs = require("fs");
var mime_types_1 = require("mime-types");
var Media = /** @class */ (function (_super) {
__extends(Media, _super);
function Media() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.hiddenFields = ["owner", "_children", "children", "parent"];
return _this;
}
Media_1 = Media;
Object.defineProperty(Media.prototype, "isDirectory", {
get: function () {
return this.is_directory == 1;
},
set: function (value) {
if (value) {
this.is_directory = 1;
}
else {
this.is_directory = 0;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(Media.prototype, "children", {
get: function () {
return Media_1.find({ where: { parent: this } });
},
enumerable: false,
configurable: true
});
Media.prototype.remove = function () {
return __awaiter(this, void 0, void 0, function () {
var _i, _a, child, k;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!this.isDirectory) return [3 /*break*/, 6];
_i = 0;
return [4 /*yield*/, this.children];
case 1:
_a = _b.sent();
_b.label = 2;
case 2:
if (!(_i < _a.length)) return [3 /*break*/, 5];
child = _a[_i];
return [4 /*yield*/, child.remove()];
case 3:
_b.sent();
_b.label = 4;
case 4:
_i++;
return [3 /*break*/, 2];
case 5: return [2 /*return*/, _super.prototype.remove.call(this)];
case 6: return [4 /*yield*/, _super.prototype.remove.call(this)];
case 7:
k = _b.sent();
app_1.app.config.ufs.unlink(this.path, function () { });
return [2 /*return*/, k];
}
});
});
};
/**
* Create a cropped image starting of the current.
* The image will be placed in the same directory as the original.
* @param config: The configuration object containing the crop parameters
* @return a promise with the new @type Media
*/
Media.prototype.resizeToNewEntity = function (config) {
return __awaiter(this, void 0, void 0, function () {
var cachedPath, img, newFileName, path, newMedia, stat;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, app_1.app.config.ufs.getToCache(this.fileName, app_1.app.config.cachePath)];
case 1:
cachedPath = _a.sent();
return [4 /*yield*/, Jimp.read(cachedPath)];
case 2:
img = _a.sent();
return [4 /*yield*/, img.rotate(config.rotate)];
case 3:
img = _a.sent();
return [4 /*yield*/, img.resize(img.getWidth() * Math.round(config.scaleX), img.getHeight() * Math.round(config.scaleY))];
case 4:
img = _a.sent();
return [4 /*yield*/, img.crop(Math.round(config.x), Math.round(config.y), Math.round(config.width), Math.round(config.height))];
case 5:
img = _a.sent();
newFileName = uuid();
path = app_1.app.config.cachePath;
return [4 /*yield*/, img.writeAsync(path + "/" + newFileName)];
case 6:
_a.sent();
return [4 /*yield*/, app_1.app.config.ufs.uploadFileFromCache(newFileName, path)];
case 7:
_a.sent();
newMedia = new Media_1();
newMedia.isDirectory = false;
newMedia.originalName = copiedName(this.originalName);
newMedia.mimetype = this.mimetype;
return [4 /*yield*/, app_1.app.config.ufs.stat(newFileName)];
case 8:
stat = _a.sent();
newMedia.size = stat.size;
newMedia.fileName = newFileName;
newMedia.path = newFileName;
newMedia.owner = this.owner;
newMedia.parent = this.parent;
newMedia.width = config.width;
newMedia.height = config.height;
return [4 /*yield*/, newMedia.save()];
case 9: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Generate a new MediaEntity from an uploaded file using the Multer library
* @param uploadMedia the multer File
* @param user the user performing the request (aka the onwer of the file)
* @param directory the (optional) virtual parent directory
*/
Media.persist = function (uploadMedia, user, directory) {
return __awaiter(this, void 0, void 0, function () {
var m, cachedPath, img, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
m = new Media_1();
return [4 /*yield*/, app_1.app.config.ufs.uploadFile(uploadMedia)];
case 1:
uploadMedia = _a.sent();
m.originalName = uploadMedia.originalname;
m.isDirectory = false;
m.mimetype = uploadMedia.mimetype;
m.size = uploadMedia.size;
m.fileName = uploadMedia.filename;
m.path = uploadMedia.path;
m.owner = user;
if (directory) {
m.parent = directory;
}
return [4 /*yield*/, app_1.app.config.ufs.getToCache(m.fileName, app_1.app.config.cachePath)];
case 2:
cachedPath = _a.sent();
if (!m.mimetype.startsWith('image')) return [3 /*break*/, 6];
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 6]);
return [4 /*yield*/, Jimp.read(cachedPath)];
case 4:
img = _a.sent();
m.width = img.getWidth();
m.height = img.getHeight();
return [3 /*break*/, 6];
case 5:
e_1 = _a.sent();
console.log("Error obtaining the metadata of the image.");
console.log("Image path: " + uploadMedia.path);
console.error(e_1);
return [3 /*break*/, 6];
case 6: return [2 /*return*/, m.save()];
}
});
});
};
/**
* Generate a new MediaEntity from a local temporary file
* @param originalName the original name of the file
* @param path the temporary path of the file
* @param user the user perfrming the request (aka the owner of the file)
* @param directory the (optional) virtual parent directory
*/
Media.persistTempFile = function (originalName, path, user, directory) {
return __awaiter(this, void 0, void 0, function () {
var m, _a, uploadedFile;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
m = new Media_1();
m.originalName = originalName;
m.isDirectory = false;
m.mimetype = mime_types_1.lookup(path) || '';
_a = m;
return [4 /*yield*/, stat(path)];
case 1:
_a.size = (_b.sent()).size;
return [4 /*yield*/, app_1.app.config.ufs.uploadTempFile(path)];
case 2:
uploadedFile = _b.sent();
m.fileName = uploadedFile.fileName;
m.path = uploadedFile.path;
m.owner = user;
if (directory) {
m.parent = directory;
}
return [2 /*return*/, m.save()];
}
});
});
};
Media.mkdir = function (name, user, directory) {
return __awaiter(this, void 0, void 0, function () {
var names, prev, i, n, where, m;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
names = normalizePath(name).split("/");
prev = directory;
i = 0;
_a.label = 1;
case 1:
if (!(i < names.length)) return [3 /*break*/, 6];
n = names[i];
if (!prev) {
prev = null;
}
where = {
where: {
originalName: n,
is_directory: 1,
parent: prev
}
};
return [4 /*yield*/, Media_1.findOne(where)];
case 2:
m = _a.sent();
if (!!m) return [3 /*break*/, 4];
m = new Media_1();
m.originalName = n;
m.isDirectory = true;
if (user) {
m.owner = user;
}
if (prev) {
m.parent = prev;
}
return [4 /*yield*/, m.save()];
case 3:
_a.sent();
_a.label = 4;
case 4:
prev = m;
_a.label = 5;
case 5:
i++;
return [3 /*break*/, 1];
case 6: return [2 /*return*/, prev];
}
});
});
};
Media.getFolder = function (path) {
return __awaiter(this, void 0, void 0, function () {
var names, prev, _i, names_1, n;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
names = normalizePath(path).split("/");
prev = null;
_i = 0, names_1 = names;
_a.label = 1;
case 1:
if (!(_i < names_1.length)) return [3 /*break*/, 4];
n = names_1[_i];
return [4 /*yield*/, Media_1.findOne({
where: {
originalName: n,
is_directory: 1,
parent: prev
}
})];
case 2:
prev = _a.sent();
if (!prev) {
return [2 /*return*/, prev];
}
_a.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, prev];
}
});
});
};
Media.findBySlug = function (slug) {
return Media_1.findOne({ where: { slug: slug, is_directory: 0 } });
};
Media.findBySlugOrId = function (key) {
return Media_1.getRepository()
.createQueryBuilder("m")
.where("m.slug = :slug AND is_directory = 0", { slug: key })
.orWhere("m.id = :id AND is_directory = 0", { id: key })
.getOne();
};
Media.findOneWithParent = function (id) {
return Media_1.findOne({ where: { id: id }, relations: ["parent"] });
};
var Media_1;
__decorate([
typeorm_1.PrimaryGeneratedColumn(),
__metadata("design:type", Number)
], Media.prototype, "id", void 0);
__decorate([
typeorm_1.Column(),
__metadata("design:type", String)
], Media.prototype, "originalName", void 0);
__decorate([
typeorm_1.Column({ unique: true, default: null }),
__metadata("design:type", String)
], Media.prototype, "slug", void 0);
__decorate([
typeorm_1.Column({ type: "smallint", default: 0 }),
__metadata("design:type", Number)
], Media.prototype, "is_directory", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", String)
], Media.prototype, "mimetype", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", Number)
], Media.prototype, "size", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", String)
], Media.prototype, "fileName", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", String)
], Media.prototype, "path", void 0);
__decorate([
typeorm_1.ManyToOne(function (_) { return Media_1; }, function (media) { return media._children; }),
__metadata("design:type", Media)
], Media.prototype, "parent", void 0);
__decorate([
typeorm_1.OneToMany(function (_) { return Media_1; }, function (media) { return media.parent; }),
__metadata("design:type", Array)
], Media.prototype, "_children", void 0);
__decorate([
typeorm_1.ManyToOne(function (_) { return user_entity_1.default; }, function (user) { return user.media; }, { eager: true }),
__metadata("design:type", user_entity_1.default)
], Media.prototype, "owner", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", Number)
], Media.prototype, "width", void 0);
__decorate([
typeorm_1.Column({ nullable: true }),
__metadata("design:type", Number)
], Media.prototype, "height", void 0);
Media = Media_1 = __decorate([
typeorm_1.Entity("media")
], Media);
return Media;
}(base_entity_1.default));
exports.default = Media;
function normalizePath(path) {
if (path.startsWith("/")) {
path = path.substring(1);
}
if (path.endsWith("/")) {
path = path.substring(0, path.length - 1);
}
return path;
}
function copiedName(name) {
var index = name.lastIndexOf(".");
if (index == -1) {
return name + " 1";
}
return name.substring(0, index) + " 1" + name.substring(index);
}
function stat(path) {
return new Promise(function (ok, fail) {
fs.stat(path, function (err, info) {
if (err) {
return fail(err);
}
ok(info);
});
});
}
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2x5bngvZW50aXRpZXMvbWVkaWEuZW50aXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQU1pQjtBQUNqQiw2Q0FBdUM7QUFDdkMsNkNBQWlDO0FBQ2pDLDJCQUE2QjtBQUM3Qiw2QkFBMEI7QUFDMUIsSUFBTSxJQUFJLEdBQUcsU0FBRSxDQUFDO0FBQ2hCLDhCQUE2QjtBQUU3Qix1QkFBeUI7QUFDekIseUNBQW9DO0FBYXBDO0lBQW1DLHlCQUFVO0lBQTdDO1FBQUEscUVBb09DO1FBbk9HLGtCQUFZLEdBQUcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQzs7SUFtT2hFLENBQUM7Y0FwT29CLEtBQUs7SUFVdEIsc0JBQUksOEJBQVc7YUFBZjtZQUNJLE9BQU8sSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLENBQUM7UUFDbEMsQ0FBQzthQUVELFVBQWdCLEtBQWM7WUFDMUIsSUFBSSxLQUFLLEVBQUU7Z0JBQ1AsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7YUFDekI7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7YUFDekI7UUFDTCxDQUFDOzs7T0FSQTtJQTZCRCxzQkFBSSwyQkFBUTthQUFaO1lBQ0ksT0FBTyxPQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNuRCxDQUFDOzs7T0FBQTtJQUVLLHNCQUFNLEdBQVo7Ozs7Ozs2QkFDUSxJQUFJLENBQUMsV0FBVyxFQUFoQix3QkFBZ0I7OEJBQ3FCO3dCQUFuQixxQkFBTSxJQUFJLENBQUMsUUFBUSxFQUFBOzt3QkFBbkIsS0FBQSxTQUFtQjs7OzZCQUFuQixDQUFBLGNBQW1CLENBQUE7d0JBQTVCLEtBQUs7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LElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxFQUFFO1FBQ2IsT0FBTyxJQUFJLEdBQUcsSUFBSSxDQUFDO0tBQ3RCO0lBQ0QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNuRSxDQUFDO0FBR0QsU0FBUyxJQUFJLENBQUMsSUFBWTtJQUN0QixPQUFPLElBQUksT0FBTyxDQUFDLFVBQUMsRUFBRSxFQUFFLElBQUk7UUFDeEIsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBQyxHQUFHLEVBQUUsSUFBSTtZQUNwQixJQUFJLEdBQUcsRUFBRTtnQkFDTCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNwQjtZQUNELEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwiZmlsZSI6ImVudGl0aWVzL21lZGlhLmVudGl0eS5qcyIsInNvdXJjZVJvb3QiOiIuLiJ9