UNPKG

mybatis-node

Version:

MyBatisNodeJs is a port from the The MyBatis Java data mapper framework for Node.Js.

477 lines 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs"); const moment = require("moment"); const path = require("path"); const s = require("string"); const util = require("util"); const xmldom_1 = require("xmldom"); const Context_1 = require("./Context"); class SqlCommand { constructor() { this.sql = ""; this.parameters = []; } addParameter(value) { this.parameters.push(value); } } class No { constructor(id, mapping) { this.id = id; this.children = []; } add(no) { this.children.push(no); } getSql(sqlcommand, data) { for (const prop in this.children) { if (prop in this.children) { const noson = this.children[prop]; noson.getSql(sqlcommand, data); } } return sqlcommand; } getValue(data, path) { for (let i = 0; typeof data === "object" && i < path.length; ++i) { if (data) { data = data[path[i]]; } } return data; } processexpression(expression, sqlcommand, data) { let myArray; const regex = new RegExp("#{([a-z.A-Z0-9_]+)}", "ig"); while ((myArray = regex.exec(expression)) !== null) { const stretch = myArray[0]; const propertyvalue = this.getValue(data, myArray[1].split(".")); if (propertyvalue == null || typeof propertyvalue === "number" || typeof propertyvalue === "boolean" || typeof propertyvalue === "string") { expression = expression.replace(stretch, "?"); sqlcommand.addParameter(propertyvalue); } else if (util.isDate(propertyvalue)) { const value = moment(propertyvalue).format("YYYY-MM-DD HH:mm:ss"); expression = expression.replace(stretch, "?"); sqlcommand.addParameter(value); } else if (util.isArray(propertyvalue)) { throw new Error("Can not translate snippet " + stretch + " by collection: " + propertyvalue); } } return expression; } } class NoString extends No { constructor(text, mapping) { super("", mapping); this.text = text.trim(); } getSql(sqlcommand, data) { sqlcommand.sql += super.processexpression(this.text, sqlcommand, data) + " "; } } class NoChoose extends No { constructor(mapping) { super("", mapping); } add(no) { super.add(no); if (no instanceof NoOtherwise) { this.noOtherwise = no; } } getSql(sqlcommand, data) { for (const i in this.children) { const no = this.children[i]; if (no instanceof NoWhen) { const nowhen = no; const expression = nowhen.expressionTest.replace("#{", "data.").replace("}", ""); try { eval("if( " + expression + " ) data.valueExpression = true; else data.valueExpression = false;"); } catch (err) { data.valueExpression = false; } if (data.valueExpression) { return nowhen.getSql(sqlcommand, data); } } } if (this.noOtherwise) { return this.noOtherwise.getSql(sqlcommand, data); } return ""; } } class NoWhen extends No { constructor(expressionTest, text, mapping) { super("", mapping); this.expressionTest = expressionTest; this.text = text; const regex = new RegExp("[_a-zA-Z][_a-zA-Z0-9]{0,30}", "ig"); const identifiers = []; let myArray = []; while ((myArray = regex.exec(expressionTest)) !== null) { const identifier = myArray[0]; if (identifier == "null" || identifier == "true" || identifier == "false" || identifier == "and") { continue; } identifiers.push(identifier); this.expressionTest = this.expressionTest.replace(identifier, "data." + identifier); } this.expressionTest = s(this.expressionTest).replaceAll("and", "&&").toString(); } } class NoForEach extends No { constructor(item, index, separator, opening, closure, text, collection, mapping) { super("", mapping); this.item = item; this.index = index; this.separator = separator; this.opening = opening; this.closure = closure; this.collection = collection; this.text = text.trim(); } getSql(sqlcommand, data) { const text = []; let collection = data[this.collection]; if (collection == null) { if (util.isArray(data)) { collection = data; } else { return this.opening + this.closure; } } for (const item of collection) { let myArray; const regex = new RegExp("#{([a-z.A-Z]+)}", "ig"); const expression = this.text; let newexpression = expression; while ((myArray = regex.exec(expression)) !== null) { const stretch = myArray[0]; const property = myArray[1].replace(this.item + ".", ""); const propertyvalue = this.getValue(item, property.split(".")); if (typeof propertyvalue == "number" || typeof propertyvalue == "string" || typeof propertyvalue == "boolean") { newexpression = newexpression.replace(stretch, "?"); sqlcommand.addParameter(propertyvalue); } } text.push(newexpression); } const sql = this.opening + text.join(this.separator) + this.closure; sqlcommand.sql += sql; return sqlcommand; } } class NoIf extends No { constructor(expressionTest, text, mapping) { super("", mapping); this.expressionTest = expressionTest; this.text = text; const regex = new RegExp("[_a-zA-Z][_a-zA-Z0-9]{0,30}", "ig"); const identifiers = []; let myArray = []; while ((myArray = regex.exec(expressionTest)) !== null) { const identifier = myArray[0]; if (identifier == "null") { continue; } identifiers.push(identifier); this.expressionTest = this.expressionTest.replace(identifier, "data." + identifier); } } getSql(sqlcommand, data) { const expression = this.expressionTest.replace("#{", "data.").replace("}", ""); try { if (expression) { eval("if( " + expression + " ) data.valueExpression = true; else data.valueExpression = false;"); } } catch (err) { data.valueExpression = false; } if (data.valueExpression == false) { return ""; } super.getSql(sqlcommand, data) + " "; } } class NoOtherwise extends No { constructor(text, mapping) { super("", mapping); this.text = text; } getSql(sqlcommand, data) { let myArray; const regex = new RegExp("#{([a-z.A-Z]+)}", "ig"); let expression = this.text; while ((myArray = regex.exec(this.text)) !== null) { const stretch = myArray[0]; const propertyvalue = this.getValue(data, myArray[1].split(".")); if (typeof propertyvalue == "number" || typeof propertyvalue == "string" || typeof propertyvalue == "boolean") { expression = expression.replace(stretch, "?"); sqlcommand.addParameter(propertyvalue); } } sqlcommand.sql += expression + " "; } } class Main { constructor(pool) { this.pool = pool; this.context = new Context_1.default(); } read(name, gchild, mapping) { const id = gchild.getAttributeNode("id").value; const incharge = new No(id, mapping); for (const no of Array.from(gchild.childNodes)) { if (no.nodeName == "choose") { this.readChoose(no, incharge, mapping); } else if (no.nodeName == "if") { this.readIf(no, incharge, mapping); } else if (no.nodeName == "foreach") { this.readForEach(no, incharge, mapping); } else { if (no.hasChildNodes() == false) { const noString = new NoString(no.textContent, mapping); incharge.add(noString); } } } return incharge; } readForEach(no, nomain, mapping) { let valueSeparador = ""; if (no.getAttributeNode("separator")) { valueSeparador = no.getAttributeNode("separator").value; } let valueAverage = ""; if (no.getAttributeNode("open")) { valueAverage = no.getAttributeNode("open").value; } let closingvalue = ""; if (no.getAttributeNode("close")) { closingvalue = no.getAttributeNode("close").value; } let valueIndex = ""; if (no.getAttributeNode("index")) { valueIndex = no.getAttributeNode("index").value; } let valueCollection = ""; if (no.getAttributeNode("collection")) { valueCollection = no.getAttributeNode("collection").value; } const noday = new NoForEach(no.getAttributeNode("item").value, valueIndex, valueSeparador, valueAverage, closingvalue, no.textContent, valueCollection, mapping); nomain.add(noday); } readIf(no, nomain, mapping) { const noIf = new NoIf(no.getAttributeNode("test").value, no.childNodes[0].toString(), mapping); for (let i = 0; i < no.childNodes.length; i++) { const noson = no.childNodes[i]; if (noson.nodeName == "choose") { this.readChoose(noson, noIf, mapping); } else if (noson.nodeName == "if") { this.readIf(noson, noIf, mapping); } else if (noson.nodeName == "foreach") { this.readForEach(noson, noIf, mapping); } else { if (noson.hasChildNodes() == false) { const noString = new NoString(noson.textContent, mapping); noIf.add(noString); } } } nomain.add(noIf); } readChoose(no, nomain, mapping) { const nohead = new NoChoose(mapping); for (const noson of no.childNodes) { if (noson.nodeName == "when") { nohead.add(this.readNoWhen(noson, no, mapping)); } else if (noson.nodeName == "otherwise") { nohead.add(new NoOtherwise(noson.childNodes[0].toString(), mapping)); } } nomain.add(nohead); } readNoWhen(no, noPrivate, mapping) { const expressionTest = no.getAttributeNode("test").value; const nowhen = new NoWhen(expressionTest, "", mapping); for (const noson of no.childNodes) { if (noson.nodeName == "choose") { this.readChoose(noson, nowhen, mapping); } else if (noson.nodeName == "if") { this.readIf(noson, nowhen, mapping); } else if (noson.nodeName == "foreach") { this.readForEach(noson, nowhen, mapping); } else if (noson.hasChildNodes() == false) { const noString = new NoString(noson.textContent, mapping); nowhen.add(noString); } } return nowhen; } process(dir_xml) { const mapNos = {}; const templateManager = new TemplateMapManager(this.context, this.pool); const models = {}; const stats = fs.statSync(dir_xml); if (stats.isFile()) { const mapping = this.processFile(dir_xml); templateManager.add(mapping); return templateManager; } else if (stats.isDirectory()) { const files = fs.readdirSync(dir_xml); for (const prop in files) { const archive = files[prop]; const mapping = this.processFile(path.resolve(dir_xml, archive)); templateManager.add(mapping); } return templateManager; } } processFile(filename) { if (fs.lstatSync(filename).isDirectory()) { return null; } const xml = fs.readFileSync(filename).toString(); const xmlDoc = new xmldom_1.DOMParser().parseFromString(xml); if (xmlDoc.documentElement.nodeName != "mapper") { return null; } const we = xmlDoc.documentElement.childNodes; const mapping = new Mapping(xmlDoc.documentElement.getAttributeNode("namespace").value); for (const noXml of Array.from(we)) { if (noXml.nodeName != "#text" && noXml.nodeName != "#comment") { const no = this.read(noXml.nodeName, noXml, mapping); mapping.add(no); } } return mapping; } } exports.Main = Main; class TemplateMapManager { constructor(context, pool) { this.mappings = []; this.mapMapping = {}; this.context = context; this.pool = pool; } add(mapping) { if (mapping == null) { return; } this.mapMapping[mapping.name] = mapping; this.mappings.push(mapping); } getNo(fullnameResultMap) { const nameNamespace = fullnameResultMap.split(".")[0]; const id = fullnameResultMap.split(".")[1]; const mapping = this.mapMapping[nameNamespace]; return mapping.getNo(id); } insert(fullname, object) { return new Promise((resolve, reject) => { const no = this.getNo(fullname); const sqlcommand = new SqlCommand(); no.getSql(sqlcommand, object); this.connection((connection) => { connection.query(sqlcommand.sql, sqlcommand.parameters, (err, rows, fields) => { if (err) { reject(err); } resolve(rows.affectedRows); }); }); }); } update(fullname, object) { return new Promise((resolve, reject) => { const no = this.getNo(fullname); const sqlcommand = new SqlCommand(); const sql = no.getSql(sqlcommand, object); this.connection((connection) => { connection.query(sqlcommand.sql, sqlcommand.parameters, function (err, rows, fields) { if (err) { reject(err); } resolve(rows.affectedRows); }); }); }); } remove(fullname, object) { return new Promise((resolve, reject) => { const no = this.getNo(fullname); const sqlcommand = new SqlCommand(); const sql = no.getSql(sqlcommand, object); this.connection((connection) => { connection.query(sqlcommand.sql, sqlcommand.parameters, (err, rows, fields) => { if (err) { reject(err); } resolve(rows.affectedRows); }); }); }); } async selectOne(fullname, data) { const objects = await this.selectList(fullname, data); if (objects.length == 1) { return objects[0]; } return null; } selectList(fullname, data) { return new Promise((resolve, reject) => { const no = this.getNo(fullname); const sqlcommand = new SqlCommand(); no.getSql(sqlcommand, data); this.connection(connection => { connection.query(sqlcommand.sql, sqlcommand.parameters, (err, rows, fields) => { if (err) { reject(err); } resolve(rows); }); }); }); } connection(callback) { return this.context.getConnected(callback, this.pool); } transaction(callback) { return this.context.initiationTransaction(callback, this.pool); } } class Mapping { constructor(name) { this.name = name; this.children = []; this.nosPorId = {}; } add(noson) { this.children.push(noson); this.nosPorId[noson.id] = noson; } getNo(id) { return this.nosPorId[id]; } } //# sourceMappingURL=No.js.map