@smallprod/models
Version:
433 lines (432 loc) • 22 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const entitymanager_1 = __importDefault(require("./entitymanager"));
const create_query_1 = __importDefault(require("./querys/create.query"));
const delete_query_1 = __importDefault(require("./querys/delete.query"));
const find_query_1 = __importDefault(require("./querys/find.query"));
const update_query_1 = __importDefault(require("./querys/update.query"));
class Entity {
constructor() {
this.persisted = false;
this.relations = [];
this.create = async (dbName = null, context) => {
var _a, _b;
const base = this;
const query = new create_query_1.default(base.constructor.tableName);
const nonPersistentColumns = (_a = base.constructor.nonPersistentColumns) !== null && _a !== void 0 ? _a : [];
const primaryKeys = (_b = base.constructor.primaryKeys) !== null && _b !== void 0 ? _b : [];
let column;
for (column of base.constructor.columns) {
if (!primaryKeys.includes(column.key) &&
!(base[column.key] instanceof Array) &&
typeof base[column.key] !== 'function') {
if (typeof base[column.key] !== 'object' ||
typeof base[column.key] === null) {
query.setAttribute(column.fieldName, base[column.key]);
}
else if (base[column.key] instanceof Date) {
const field = base.constructor.columns.find((f) => f.name === column.name);
if (field) {
const d = base[column.key];
let formattedD = '';
switch (field.type) {
case 'date': {
formattedD = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
break;
}
case 'datetime': {
formattedD = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()} ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
break;
}
case 'timestamp': {
formattedD = d.getTime().toString();
break;
}
case 'time': {
formattedD = `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
break;
}
default: {
formattedD = '';
}
}
if (formattedD) {
query.setAttribute(column.fieldName, formattedD);
}
}
}
}
}
const manyToManyQueries = [];
base.constructor.relations.forEach((relation) => {
if (base[relation.fieldName]) {
switch (relation.type) {
case 'manytomany':
const rel = this.relations.find((r) => r.entity === relation.entity);
const relData = rel ? rel.data : [];
const relationTable = relation.relationTable;
if (relationTable) {
base[relation.fieldName].forEach((elem) => {
if (elem.persisted &&
!relData.includes(elem[elem.constructor.id.key])) {
const manyToManyQuery = new create_query_1.default(relationTable);
const tableName = elem.constructor.tableName;
manyToManyQuery.setAttribute(`${tableName.endsWith('s')
? tableName.substr(0, tableName.length - 1)
: tableName}_id`, elem[elem.constructor.id.key]);
manyToManyQueries.push(manyToManyQuery);
}
});
}
break;
case 'manytoone':
if (base[relation.fieldName].persisted) {
query.setAttribute(`${relation.fieldName}_id`, base[relation.fieldName][base[relation.fieldName].constructor.id.key]);
}
break;
case 'onetomany':
break;
default:
}
}
});
const res = await query.exec(dbName);
if (res) {
if (base.constructor.id) {
this.persisted = true;
base[base.constructor.id.key] = res;
entitymanager_1.default.addEntity(this, context);
await manyToManyQueries.reduce(async (prev, cur) => {
await prev;
const tableName = base.constructor.tableName;
cur.setAttribute(`${tableName.endsWith('s')
? tableName.substr(0, tableName.length - 1)
: tableName}_id`, base[base.constructor.id.key]);
await cur.exec(dbName);
}, Promise.resolve());
}
return this;
}
return null;
};
this.update = async (dbName = null) => {
var _a, _b;
const base = this;
const query = new update_query_1.default(base.constructor.tableName);
const nonPersistentColumns = (_a = base.constructor.nonPersistentColumns) !== null && _a !== void 0 ? _a : [];
const primaryKeys = (_b = base.constructor.primaryKeys) !== null && _b !== void 0 ? _b : [];
let column;
for (column of base.constructor.columns) {
if (!primaryKeys.includes(column.key) &&
!(base[column.key] instanceof Array) &&
typeof base[column.key] !== 'function') {
if (typeof base[column.key] !== 'object' ||
typeof base[column.key] === null) {
query.setAttribute(column.fieldName, base[column.key]);
}
else if (base[column.key] instanceof Date) {
const field = base.constructor.columns.find((f) => f.key === column.key);
if (field) {
const d = base[column.key];
let formattedD = '';
switch (field.type) {
case 'date': {
formattedD = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
break;
}
case 'datetime': {
formattedD = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()} ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
break;
}
case 'timestamp': {
formattedD = d.getTime().toString();
break;
}
case 'time': {
formattedD = `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
break;
}
default: {
formattedD = '';
}
}
if (formattedD) {
query.setAttribute(column.fieldName, formattedD);
}
}
}
}
}
if (base.constructor.id) {
query.where(base.constructor.id.fieldName, '=', base[base.constructor.id.key]);
}
else {
throw new Error('No specified id');
}
await base.constructor.relations.reduce(async (prev, relation) => {
await prev;
if (base[relation.fieldName]) {
switch (relation.type) {
case 'manytomany': {
const rel = this.relations.find((r) => r.entity === relation.entity);
const relData = rel ? rel.data : [];
const relationTable = relation.relationTable;
if (relationTable) {
const curTableName = base.constructor.tableName;
const curTableField = `${curTableName.endsWith('s')
? curTableName.substr(0, curTableName.length - 1)
: curTableName}_id`;
const removeOldQuery = new delete_query_1.default(relationTable);
removeOldQuery.where(curTableField, '=', base[base.constructor.id.key]);
await removeOldQuery.exec(dbName);
await base[relation.fieldName].reduce(async (previous, elem) => {
await previous;
if (elem.persisted &&
!relData.includes(elem[elem.constructor.id.key])) {
const tableName = elem.constructor.tableName;
const tableField = `${tableName.endsWith('s')
? tableName.substr(0, tableName.length - 1)
: tableName}_id`;
const manyToManyQuery = new create_query_1.default(relationTable);
manyToManyQuery.setAttribute(tableField, elem[elem.constructor.id.key]);
manyToManyQuery.setAttribute(curTableField, base[base.constructor.id.key]);
await manyToManyQuery.exec(dbName);
}
}, Promise.resolve());
}
break;
}
case 'manytoone':
if (base[relation.fieldName].persisted) {
query.setAttribute(`${relation.fieldName}_id`, base[relation.fieldName][base[relation.fieldName].constructor.id.key]);
}
break;
case 'onetomany':
break;
default:
}
}
}, Promise.resolve());
const res = await query.exec(dbName);
if (res) {
return this;
}
return null;
};
this.delete = async (dbName = null, context) => {
const base = this;
const query = new delete_query_1.default(base.constructor.tableName);
if (!base.constructor.id) {
throw new Error('No id specified');
}
await base.constructor.relations.reduce(async (prev, relation) => {
await prev;
if (relation.type === 'manytomany' && relation.relationTable) {
const curTableName = base.constructor.tableName;
const curTableField = `${curTableName.endsWith('s')
? curTableName.substr(0, curTableName.length - 1)
: curTableName}_id`;
const deleteQuery = new delete_query_1.default(relation.relationTable);
deleteQuery.where(curTableField, '=', base[base.constructor.id.key]);
await deleteQuery.exec(dbName);
}
}, Promise.resolve());
query.where(base.constructor.id.fieldName, '=', base[base.constructor.id.key]);
const res = await query.exec(dbName);
if (res) {
entitymanager_1.default.removeEntity(this, context);
return true;
}
return false;
};
this.fetch = async (field, context, dbName) => {
var _a;
const base = this;
const relation = base.constructor.relations.find((r) => r.fieldName === field);
if (relation) {
const rel = entitymanager_1.default.entities.find((e) => e.tableName === relation.entity);
if (rel) {
const ent = rel.entity;
switch (relation.type) {
case 'manytomany': {
const relationTable = relation.relationTable;
if (relationTable) {
const tableName = base.constructor.tableName;
const relations = await new find_query_1.default(relationTable)
.where(`${tableName.endsWith('s')
? tableName.substr(0, tableName.length - 1)
: tableName}_id`, '=', base[base.constructor.id.key])
.exec(dbName);
if (relations && relations.length) {
this.relations.push({
entity: relation.entity,
data: relations,
});
base[relation.fieldName] = await ent
.findMany(context, dbName)
.where(((_a = ent.id) === null || _a === void 0 ? void 0 : _a.fieldName) || '', 'IN', relations.map((r) => r[`${ent.tableName.endsWith('s')
? ent.tableName.substr(0, ent.tableName.length - 1)
: ent.tableName}_id`]))
.exec(dbName);
}
else {
base[field] = [];
}
}
break;
}
case 'manytoone': {
if (base[`${relation.entity}_id`]) {
base[field] = await ent.findById(base[`${relation.entity}_id`], context, dbName);
}
break;
}
case 'onetomany': {
base[field] = await ent
.findMany(context, dbName)
.where(`${base.constructor.tableName}_id`, '=', base[base.constructor.id.key])
.exec(dbName);
break;
}
default:
}
}
}
};
}
static findOne(context) {
const query = new find_query_1.default(this.tableName, async (res) => {
if (res.length) {
return await this.generateEntity(res[0], context);
}
return null;
}, this.dbName);
query.limit(1);
return query;
}
static findMany(context, dbName) {
const query = new find_query_1.default(this.tableName, async (res) => {
const result = [];
await res.reduce(async (prev, r) => {
await prev;
result.push(await this.generateEntity(r, context, dbName));
}, Promise.resolve());
return result;
}, this.dbName);
return query;
}
static async findById(id, context, dbName) {
if (!this.id)
throw new Error('No id specified');
const entity = entitymanager_1.default.findEntity(this.tableName, id);
if (entity)
return entity;
const query = new find_query_1.default(this.tableName);
query.where(this.id.fieldName, '=', id);
const res = await query.exec(dbName);
if (res.length) {
return await this.generateEntity(res[0], context, dbName);
}
return null;
}
static async deleteById(id, context, dbName) {
const query = new delete_query_1.default(this.tableName);
if (!this.id)
throw new Error('No id specified');
query.where(this.id.fieldName, '=', id);
const res = await query.exec(dbName);
if (res) {
const entity = entitymanager_1.default.findEntity(this.tableName, id, context);
if (entity)
entitymanager_1.default.removeEntity(entity, context);
}
return res;
}
static async generateEntity(res, context, dbName) {
const newObj = this.create();
newObj.persisted = true;
for (const [key, value] of Object.entries(res)) {
const field = this.columns.find((f) => f.fieldName === key);
if (field) {
switch (field.type) {
case 'date':
case 'datetime':
case 'timestamp':
case 'time':
newObj[field.key] = new Date(value);
break;
default:
newObj[field.key] = value;
}
}
else {
newObj[key] = value;
}
}
const entity = entitymanager_1.default.findEntity(newObj.constructor.tableName, newObj[newObj.constructor.id.key], context);
if (entity) {
return entity;
}
entitymanager_1.default.addEntity(newObj, context);
await this.relations.reduce(async (prev, cur) => {
var _a, _b, _c;
await prev;
if (cur.autoFetch) {
const relationEntity = entitymanager_1.default.entities.find((e) => e.tableName === cur.entity);
if (relationEntity) {
const ent = relationEntity.entity;
switch (cur.type) {
case 'manytomany': {
const relationTable = cur.relationTable;
if (relationTable) {
const relations = await new find_query_1.default(relationTable)
.where(`${this.tableName.endsWith('s')
? this.tableName.substr(0, this.tableName.length - 1)
: this.tableName}_id`, '=', res[((_a = this.id) === null || _a === void 0 ? void 0 : _a.fieldName) || ''])
.exec(dbName);
if (relations && relations.length) {
newObj.relations.push({
entity: cur.entity,
data: relations,
});
newObj[cur.fieldName] = await ent
.findMany(context, dbName)
.where(((_b = ent.id) === null || _b === void 0 ? void 0 : _b.fieldName) || '', 'IN', relations.map((r) => r[`${ent.tableName.endsWith('s')
? ent.tableName.substr(0, ent.tableName.length - 1)
: ent.tableName}_id`]))
.exec(dbName);
}
else {
newObj[cur.fieldName] = [];
}
}
break;
}
case 'manytoone': {
if (res[`${cur.fieldName}_id`]) {
newObj[cur.fieldName] = await ent.findById(res[`${cur.fieldName}_id`], context, dbName);
}
break;
}
case 'onetomany': {
newObj[cur.fieldName] = await ent
.findMany(context)
.where(`${this.tableName}_id`, '=', res[((_c = this.id) === null || _c === void 0 ? void 0 : _c.fieldName) || ''])
.exec(dbName);
break;
}
default:
}
}
}
}, Promise.resolve());
return newObj;
}
}
exports.default = Entity;
Entity.initialized = false;
Entity.create = () => {
};