@azteam/mongo-model
Version:
N/A
438 lines (437 loc) • 18 kB
JavaScript
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Model = exports.DefaultAttributes = exports.DataTypes = void 0;
Object.defineProperty(exports, "Schema", {
enumerable: true,
get: function get() {
return _mongoose.Schema;
}
});
exports.validationRuleObjectId = validationRuleObjectId;
var _htmlMinifier = require("html-minifier");
var _lodash = _interopRequireDefault(require("lodash"));
var _mongoose = _interopRequireWildcard(require("mongoose"));
var _mongooseLeanVirtuals = _interopRequireDefault(require("mongoose-lean-virtuals"));
var _mongoosePaginateV = _interopRequireDefault(require("mongoose-paginate-v2"));
var _sanitizeHtml = _interopRequireDefault(require("sanitize-html"));
var _constant = require("@azteam/constant");
var _util = require("@azteam/util");
var _validator = _interopRequireWildcard(require("@azteam/validator"));
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var DataTypes = exports.DataTypes = {
BOOLEAN: Boolean,
ID: _mongoose["default"].Types.ObjectId,
OBJECT: _mongoose["default"].Mixed,
STRING: String,
NUMBER: Number,
ARRAY: Array
};
function validationRuleObjectId() {
var optional = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
return {
type: 'objectID',
ObjectID: DataTypes.ID,
optional: optional
};
}
var DefaultAttributes = exports.DefaultAttributes = {
SLUG: {
slug: {
type: DataTypes.STRING,
unique: true,
guard: true,
allowCreate: true,
validationRule: (0, _validator.schemaSlug)(true)
},
related_slugs: {
type: DataTypes.ARRAY,
index: true,
"default": [],
validationRule: (0, _validator.schemaArray)((0, _validator.schemaSlug)(), true)
}
},
TRASH: {
deleted_at: {
type: DataTypes.NUMBER,
"default": 0,
validationRule: (0, _validator.schemaNumber)(true),
guard: true
},
deleted_id: {
type: DataTypes.ID,
validationRule: validationRuleObjectId(true),
guard: true
}
},
META_DATA: {
indexing_domains: {
type: DataTypes.ARRAY,
"default": [],
validationRule: (0, _validator.schemaArray)((0, _validator.schemaObject)({
domain: (0, _validator.schemaString)(),
indexed: (0, _validator.schemaBoolean)()
}), true)
},
metadata_disable: {
type: DataTypes.NUMBER,
"default": 0,
validationRule: (0, _validator.schemaBoolean)(true)
},
metadata_title: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaString)(0, 1000, true)
},
metadata_description: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaString)(0, 3000, true)
},
metadata_keywords: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaString)(0, 1000, true)
},
metadata_image_url: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaUrl)(true)
},
metadata_title_og: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaString)(0, 1000, true)
},
metadata_description_og: {
type: DataTypes.STRING,
validationRule: (0, _validator.schemaString)(0, 3000, true)
},
ld_json: {
type: DataTypes.STRING,
"default": '{}',
validationRule: (0, _validator.schemaJSON)(true)
}
},
MODIFY: {
created_at: {
type: DataTypes.NUMBER,
"default": 0,
validationRule: (0, _validator.schemaNumber)(true),
guard: true,
index: true
},
created_id: {
type: DataTypes.ID,
validationRule: validationRuleObjectId(true),
guard: true
},
modified_at: {
type: DataTypes.NUMBER,
"default": 0,
validationRule: (0, _validator.schemaNumber)(true),
guard: true,
index: true
},
modified_id: {
type: DataTypes.ID,
validationRule: validationRuleObjectId(true),
guard: true
}
}
};
function sanitize(content) {
var sanitizeContent = (0, _sanitizeHtml["default"])(content, {
allowedTags: ['img', 'span', 'address', 'article', 'aside', 'footer', 'header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nav', 'section', 'blockquote', 'figcaption', 'figure', 'hr', 'li', 'main', 'ol', 'p', 'pre', 'ul', 'a', 'b', 'br', 'code', 'em', 'i', 'kbd', 'mark', 'q', 's', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'wbr', 'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'video', 'iframe', 'svg', 'summary', 'details'],
allowedAttributes: {
a: ['href', 'name', 'target', 'rel'],
img: ['src', 'alt', 'title'],
iframe: ['src'],
'*': ['style', 'itemscope', 'itemtype', 'itemprop'],
details: ['open']
},
allowedStyles: {
'*': {
// Match HEX and RGB
// eslint-disable-next-line
color: [/^\#(0x)?[0-9a-f]+$/i, /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/],
'text-align': [/^left$/, /^right$/, /^center$/, /^justify$/],
// Match any number with px, em, or %
'font-size': [/^\d+(?:px|em|%)$/],
'font-style': [/^.*$/],
'font-weight': [/^bold$/],
'font-family': [/^.*$/],
'max-width': [/^\d+(?:px|em|%)$/],
'max-height': [/^\d+(?:px|em|%)$/],
padding: [/^\d+(?:px|em|%)$/],
'padding-left': [/^\d+(?:px|em|%)$/],
'padding-right': [/^\d+(?:px|em|%)$/],
'padding-top': [/^\d+(?:px|em|%)$/],
'padding-bottom': [/^\d+(?:px|em|%)$/],
margin: [/^\d+(?:px|em|%)$/],
'margin-top': [/^\d+(?:px|em|%)$/],
'margin-left': [/^\d+(?:px|em|%)$/],
'margin-right': [/^\d+(?:px|em|%)$/],
'margin-bottom': [/^\d+(?:px|em|%)$/],
'border-radius': [/^\d+(?:px|em|%)$/],
'vertical-align': [/^length$/, /^%$/, /^sub/, /^super$/, /^top$/, /^text-top$/, /^middle/, /^bottom$/, /^text-bottom$/, /^initial$/, /^inherit$/],
colspan: [/^\d+/]
}
},
allowedSchemes: ['http', 'https', 'mailto', 'tel'],
allowedSchemesAppliedToAttributes: ['href', 'src'],
allowedIframeHostnames: ['www.youtube.com']
});
return (0, _htmlMinifier.minify)(sanitizeContent.trim(), {
collapseWhitespace: true
});
}
function createSchema(Model, colAttributes, isTrash) {
var validationRules = {};
var newColAttributes = _lodash["default"].cloneDeep(colAttributes);
var newIndexes = _lodash["default"].cloneDeep(Model.indexes);
var decimals = [];
var guardLoadData = [];
var allowCreateLoadData = [];
_lodash["default"].map(newColAttributes, function (col, key) {
if (isTrash) {
delete col.index;
delete col.unique;
delete col.text;
}
if (col.type) {
if (col.type.name === 'String') {
col.trim = true;
}
}
if (col.validationRule) {
validationRules[key] = col.validationRule;
delete col.validationRule;
}
if (col.guard) {
guardLoadData.push(key);
delete col.guard;
}
if (col.allowCreate) {
allowCreateLoadData.push(key);
delete col.allowCreate;
}
});
var schema = new _mongoose.Schema(newColAttributes, {
toJSON: {
virtuals: true,
transform: function transform(doc, ret) {
decimals.map(function (key) {
// eslint-disable-next-line no-param-reassign
ret[key] = parseInt(ret[key], 10);
return true;
});
return ret;
}
}
});
schema.plugin(_mongoosePaginateV["default"]);
schema.pre('validate', function (next) {
(0, _validator["default"])(this.toJSON(), validationRules);
next();
});
if (isTrash) {
schema.index({
deleted_at: -1
});
} else {
newIndexes.map(function (idx) {
return schema.index(idx.index, idx.opt);
});
}
schema.pre('save', function (next) {
if (this.constructor.name !== 'EmbeddedDocument') {
var now = Math.floor(Date.now() / 1000);
this.wasNew = false;
this.modifiedFields = [];
if (this.isNew) {
this.wasNew = true;
if (this.beforeCreate) {
this.beforeCreate();
}
if (!this.created_at) {
this.created_at = now;
}
if (this.indexing_domains) {
this.indexing_domains = [];
}
}
if (this.isForceModify) {
this.modified_at = now;
}
if (this.isModified()) {
this.modifiedFields = this.modifiedPaths();
if (this.beforeModify) {
this.beforeModify();
}
this.increment();
if (!this.isNoModify && (!this.wasNew || !this.modified_at)) {
this.modified_at = now;
}
}
}
next();
});
schema.post('save', function (doc, next) {
if (this.constructor.name !== 'EmbeddedDocument') {
if (this.wasNew) {
if (this.afterCreate) {
this.afterCreate();
}
}
if (this.afterModify) {
this.afterModify();
}
}
next();
});
schema.methods.loadData = function (data) {
var _this = this;
var allows = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var newAllows = allows;
if (this.isNew) {
newAllows = [].concat(_toConsumableArray(allows), allowCreateLoadData);
}
var guardData = (0, _util.omitItem)(data, ['_id', '__v'].concat(guardLoadData), newAllows);
_lodash["default"].map(guardData, function (value, key) {
if (value !== null && value !== undefined) {
if (!_lodash["default"].isObject(data[key]) || !_lodash["default"].isEqual(_this[key], value)) {
_this[key] = value;
}
}
if (value === _this._DELETE) {
_this[key] = undefined;
}
});
return this;
};
schema.virtual('id').get(function () {
return this._id;
});
schema.plugin(_mongooseLeanVirtuals["default"]);
schema.loadClass(Model);
return schema;
}
var Model = exports.Model = /*#__PURE__*/function () {
function Model() {
_classCallCheck(this, Model);
}
return _createClass(Model, [{
key: "generateMeta",
value: function generateMeta(title, description, keywords) {
var image = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
this.metadata_title = this.metadata_title ? this.metadata_title : title;
this.metadata_title_og = this.metadata_title_og ? this.metadata_title_og : title;
this.metadata_description = this.metadata_description ? this.metadata_description : description;
this.metadata_description_og = this.metadata_description_og ? this.metadata_description_og : description;
this.metadata_keywords = this.metadata_keywords ? this.metadata_keywords : keywords;
if (image) {
this.metadata_image_url = this.metadata_image_url ? this.metadata_image_url : image;
}
}
}, {
key: "forceGenerateMeta",
value: function forceGenerateMeta(title, description, keywords) {
var image = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
this.metadata_title = title;
this.metadata_title_og = title;
this.metadata_description = description;
this.metadata_description_og = description;
this.metadata_keywords = keywords;
if (image) {
this.metadata_image_url = image;
}
}
}, {
key: "beforeCreate",
value: function beforeCreate() {
if (!this.slug) {
if (this.title) {
this.slug = (0, _util.toSlug)(this.title);
} else if (this.name) {
this.slug = (0, _util.toSlug)(this.name);
}
}
}
}, {
key: "beforeModify",
value: function beforeModify() {
if (typeof this.message === 'string') {
this.message = this.message.substring(0, 500);
}
if (this.html_content) {
this.html_content = sanitize(this.html_content);
}
}
}, {
key: "afterCreate",
value: function afterCreate() {}
}, {
key: "afterModify",
value: function afterModify() {}
}, {
key: "modify",
value: function modify() {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var allows = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (data.userId) {
this.modified_id = data.userId;
}
this.loadData(data, allows);
return this.save();
}
}, {
key: "fix",
value: function fix() {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var allows = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
this.isNoModify = true;
this.loadData(data, allows);
return this.save();
}
}], [{
key: "register",
value: function register(connection) {
var isTrash = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var schemaModel = createSchema(this, _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, this.schema), {}, {
message: {
type: DataTypes.STRING
},
status: {
type: DataTypes.NUMBER,
"default": _constant.AVAILABLE_STATUS.WAITING,
validationRule: (0, _validator.schemaEnum)(_lodash["default"].values(_constant.AVAILABLE_STATUS), true),
index: true
}
}, this.isModify ? DefaultAttributes.MODIFY : {}), this.isMetadata ? DefaultAttributes.META_DATA : {}), isTrash ? DefaultAttributes.TRASH : {}), isTrash);
this.connection = connection;
var tableName = this.tableName ? this.tableName : this.name;
var newModel = this.connection.model(this.name, schemaModel, isTrash ? "Trash".concat(tableName) : tableName);
newModel.isModify = this.isModify;
newModel.isMetadata = this.isMetadata;
return newModel;
}
}]);
}();
_defineProperty(Model, "_DELETE", '__DELETE__');
_defineProperty(Model, "isModify", true);
_defineProperty(Model, "isMetadata", false);
_defineProperty(Model, "indexes", []);
_defineProperty(Model, "schema", {});