evaengine 0.11.1 → 1.0.0
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/.ai/analysis.md +657 -0
- package/.ai/architecture/runtime.md +504 -0
- package/.ai/contracts/public-api.md +447 -0
- package/.ai/external-project-guide.md +248 -0
- package/.ai/vision.md +314 -0
- package/README.md +51 -62
- package/bin/engine +15 -21
- package/index.js +2 -18
- package/package.json +60 -64
- package/src/index.js +57 -0
- package/bin/engine-babel +0 -38
- package/lib/commands/index.js +0 -25
- package/lib/commands/index.js.map +0 -1
- package/lib/commands/interface.js +0 -51
- package/lib/commands/interface.js.map +0 -1
- package/lib/commands/make_entity.js +0 -549
- package/lib/commands/make_entity.js.map +0 -1
- package/lib/commands/tramp.js +0 -53
- package/lib/commands/tramp.js.map +0 -1
- package/lib/config/index.js +0 -98
- package/lib/config/index.js.map +0 -1
- package/lib/di.js +0 -99
- package/lib/di.js.map +0 -1
- package/lib/engine.js +0 -558
- package/lib/engine.js.map +0 -1
- package/lib/entities/index.js +0 -283
- package/lib/entities/index.js.map +0 -1
- package/lib/exceptions/index.js +0 -522
- package/lib/exceptions/index.js.map +0 -1
- package/lib/index.js +0 -105
- package/lib/index.js.map +0 -1
- package/lib/middlewares/auth.js +0 -97
- package/lib/middlewares/auth.js.map +0 -1
- package/lib/middlewares/auth_kong.js +0 -48
- package/lib/middlewares/auth_kong.js.map +0 -1
- package/lib/middlewares/debug.js +0 -68
- package/lib/middlewares/debug.js.map +0 -1
- package/lib/middlewares/index.js +0 -45
- package/lib/middlewares/index.js.map +0 -1
- package/lib/middlewares/providers.js +0 -102
- package/lib/middlewares/providers.js.map +0 -1
- package/lib/middlewares/session.js +0 -76
- package/lib/middlewares/session.js.map +0 -1
- package/lib/middlewares/trace.js +0 -241
- package/lib/middlewares/trace.js.map +0 -1
- package/lib/middlewares/validator.js +0 -71
- package/lib/middlewares/validator.js.map +0 -1
- package/lib/middlewares/view_cache.js +0 -160
- package/lib/middlewares/view_cache.js.map +0 -1
- package/lib/services/cache.js +0 -234
- package/lib/services/cache.js.map +0 -1
- package/lib/services/config.js +0 -140
- package/lib/services/config.js.map +0 -1
- package/lib/services/env.js +0 -40
- package/lib/services/env.js.map +0 -1
- package/lib/services/event_manager.js +0 -110
- package/lib/services/event_manager.js.map +0 -1
- package/lib/services/http_client.js +0 -178
- package/lib/services/http_client.js.map +0 -1
- package/lib/services/index.js +0 -70
- package/lib/services/index.js.map +0 -1
- package/lib/services/interface.js +0 -12
- package/lib/services/interface.js.map +0 -1
- package/lib/services/joi.js +0 -28
- package/lib/services/joi.js.map +0 -1
- package/lib/services/jwt_token.js +0 -120
- package/lib/services/jwt_token.js.map +0 -1
- package/lib/services/jwt_token_kong.js +0 -111
- package/lib/services/jwt_token_kong.js.map +0 -1
- package/lib/services/logger.js +0 -172
- package/lib/services/logger.js.map +0 -1
- package/lib/services/namespace.js +0 -188
- package/lib/services/namespace.js.map +0 -1
- package/lib/services/now.js +0 -69
- package/lib/services/now.js.map +0 -1
- package/lib/services/providers.js +0 -195
- package/lib/services/providers.js.map +0 -1
- package/lib/services/redis.js +0 -77
- package/lib/services/redis.js.map +0 -1
- package/lib/services/rest_client.js +0 -136
- package/lib/services/rest_client.js.map +0 -1
- package/lib/swagger/index.js +0 -684
- package/lib/swagger/index.js.map +0 -1
- package/lib/utils/api_scaffold.js +0 -253
- package/lib/utils/api_scaffold.js.map +0 -1
- package/lib/utils/case_converter.js +0 -48
- package/lib/utils/case_converter.js.map +0 -1
- package/lib/utils/crc32.js +0 -22
- package/lib/utils/crc32.js.map +0 -1
- package/lib/utils/datetime.js +0 -21
- package/lib/utils/datetime.js.map +0 -1
- package/lib/utils/host.js +0 -48
- package/lib/utils/host.js.map +0 -1
- package/lib/utils/index.js +0 -61
- package/lib/utils/index.js.map +0 -1
- package/lib/utils/pagination.js +0 -269
- package/lib/utils/pagination.js.map +0 -1
- package/lib/utils/random.js +0 -33
- package/lib/utils/random.js.map +0 -1
- package/lib/utils/smart_query.js +0 -342
- package/lib/utils/smart_query.js.map +0 -1
- package/lib/utils/test.js +0 -62
- package/lib/utils/test.js.map +0 -1
- package/lib/utils/wrapper.js +0 -9
- package/lib/utils/wrapper.js.map +0 -1
package/lib/entities/index.js
DELETED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = undefined;
|
|
7
|
-
|
|
8
|
-
var _fs = require('fs');
|
|
9
|
-
|
|
10
|
-
var _fs2 = _interopRequireDefault(_fs);
|
|
11
|
-
|
|
12
|
-
var _path = require('path');
|
|
13
|
-
|
|
14
|
-
var _path2 = _interopRequireDefault(_path);
|
|
15
|
-
|
|
16
|
-
var _assert = require('assert');
|
|
17
|
-
|
|
18
|
-
var _assert2 = _interopRequireDefault(_assert);
|
|
19
|
-
|
|
20
|
-
var _cloneDeep = require('lodash/cloneDeep');
|
|
21
|
-
|
|
22
|
-
var _cloneDeep2 = _interopRequireDefault(_cloneDeep);
|
|
23
|
-
|
|
24
|
-
var _sequelize = require('sequelize');
|
|
25
|
-
|
|
26
|
-
var _sequelize2 = _interopRequireDefault(_sequelize);
|
|
27
|
-
|
|
28
|
-
var _util = require('util');
|
|
29
|
-
|
|
30
|
-
var _util2 = _interopRequireDefault(_util);
|
|
31
|
-
|
|
32
|
-
var _di = require('../di');
|
|
33
|
-
|
|
34
|
-
var _di2 = _interopRequireDefault(_di);
|
|
35
|
-
|
|
36
|
-
var _utils = require('../utils');
|
|
37
|
-
|
|
38
|
-
var _exceptions = require('../exceptions');
|
|
39
|
-
|
|
40
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
41
|
-
|
|
42
|
-
//From https://github.com/angelxmoreno/sequelize-isunique-validator
|
|
43
|
-
_sequelize2.default.prototype.validateIsUnique = (col, msg) => {
|
|
44
|
-
const conditions = { where: {} };
|
|
45
|
-
const message = msg || `${col} must be unique`;
|
|
46
|
-
return function v(value, next) {
|
|
47
|
-
const self = this;
|
|
48
|
-
this.Model.describe().then(schema => {
|
|
49
|
-
conditions.where[col] = value;
|
|
50
|
-
Object.keys(schema).filter(field => schema[field].primaryKey).forEach(pk => {
|
|
51
|
-
conditions.where[pk] = { $ne: self[pk] };
|
|
52
|
-
});
|
|
53
|
-
}).then(() => self.Model.count(conditions).then(found => {
|
|
54
|
-
if (found !== 0) {
|
|
55
|
-
return next(message);
|
|
56
|
-
}
|
|
57
|
-
return next();
|
|
58
|
-
})).catch(next);
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
let Entities = class Entities {
|
|
63
|
-
/**
|
|
64
|
-
* @param {string} entitiesPath
|
|
65
|
-
* @param {Sequelize|Function} sequelizeInstance
|
|
66
|
-
*/
|
|
67
|
-
constructor(entitiesPath, sequelizeInstance = null) {
|
|
68
|
-
this.entitiesPath = entitiesPath;
|
|
69
|
-
this.sequelize = sequelizeInstance;
|
|
70
|
-
this.entities = {};
|
|
71
|
-
this.scanned = false;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Add tracer info to end of SQL query logging
|
|
76
|
-
* @param options
|
|
77
|
-
* @returns {*}
|
|
78
|
-
*/
|
|
79
|
-
static addTracer(options = {}) {
|
|
80
|
-
const logger = _di2.default.get('logger');
|
|
81
|
-
return Object.assign(options, {
|
|
82
|
-
benchmark: true,
|
|
83
|
-
logging: (...args) => {
|
|
84
|
-
const tracer = _di2.default.get('namespace').get('tracer');
|
|
85
|
-
const [query, cost] = args;
|
|
86
|
-
let pushed = false;
|
|
87
|
-
if (tracer && cost > 0) {
|
|
88
|
-
tracer.queries.push({
|
|
89
|
-
query,
|
|
90
|
-
cost: cost * 1000,
|
|
91
|
-
finishedAt: (0, _utils.getMicroTimestamp)()
|
|
92
|
-
});
|
|
93
|
-
pushed = true;
|
|
94
|
-
}
|
|
95
|
-
logger.verbose(...args, !pushed ? '| Tracer' : '');
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Scan all entity schemas under a special path
|
|
102
|
-
* @param entitiesPath
|
|
103
|
-
* @param withAssociate
|
|
104
|
-
* @returns {Entities}
|
|
105
|
-
*/
|
|
106
|
-
scan(entitiesPath, withAssociate = true) {
|
|
107
|
-
(0, _assert2.default)(this.sequelize && this.sequelize instanceof _sequelize2.default, 'Scan entities require a sequelize instance');
|
|
108
|
-
|
|
109
|
-
_fs2.default.readdirSync(entitiesPath).filter(file => {
|
|
110
|
-
const fileArray = file.split('.');
|
|
111
|
-
return file.indexOf('.') !== 0 && ['js', 'es6'].indexOf(fileArray.pop()) !== -1 && fileArray[0] !== 'index';
|
|
112
|
-
}).forEach(file => {
|
|
113
|
-
const entity = this.sequelize.import(_path2.default.join(entitiesPath, file));
|
|
114
|
-
this.entities[entity.name] = entity;
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
if (!withAssociate) {
|
|
118
|
-
return this;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
Object.values(this.entities).forEach(entity => {
|
|
122
|
-
if ('associate' in entity) {
|
|
123
|
-
entity.associate(this.entities);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Init sequelize instance from DI config
|
|
131
|
-
* @param withAssociate
|
|
132
|
-
* @returns {*}
|
|
133
|
-
*/
|
|
134
|
-
init(withAssociate = true) {
|
|
135
|
-
if (this.sequelize && this.scanned) {
|
|
136
|
-
return this.sequelize;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const logger = _di2.default.get('logger').getInstance();
|
|
140
|
-
if (!this.sequelize) {
|
|
141
|
-
const config = _di2.default.get('config').get();
|
|
142
|
-
const ns = _di2.default.get('namespace');
|
|
143
|
-
if (ns.isEnabled()) {
|
|
144
|
-
//Inject sequelize inner namespace, refer: http://docs.sequelizejs.com/en/latest/docs/transactions/
|
|
145
|
-
_sequelize2.default.cls = ns.use().getContext();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const dbConfig = (0, _cloneDeep2.default)(config.db);
|
|
149
|
-
if (process.env.SEQUELIZE_REPLICATION_CONFIG_KEY) {
|
|
150
|
-
dbConfig.replication = dbConfig[process.env.SEQUELIZE_REPLICATION_CONFIG_KEY];
|
|
151
|
-
}
|
|
152
|
-
this.sequelize = new _sequelize2.default(config.db.database, null, null, Object.assign({}, config.sequelize, dbConfig, Entities.addTracer()));
|
|
153
|
-
} else {
|
|
154
|
-
this.sequelize = _util2.default.isFunction(this.sequelize) ? this.sequelize() : this.sequelize;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
this.scan(this.entitiesPath, withAssociate);
|
|
158
|
-
this.scanned = true;
|
|
159
|
-
|
|
160
|
-
//TODO: mask password in logging
|
|
161
|
-
logger.debug('Entities init by scanned %s, Replication: %j', this.entitiesPath, this.sequelize.options.replication);
|
|
162
|
-
return this;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Shortcut for Sequelize query
|
|
167
|
-
* @param sql
|
|
168
|
-
* @param bind
|
|
169
|
-
* @param options
|
|
170
|
-
* @returns {*|{foo}|{}}
|
|
171
|
-
*/
|
|
172
|
-
query(sql, bind = {}, options = {}) {
|
|
173
|
-
return this.getInstance().query(sql, Object.assign({
|
|
174
|
-
type: this.getSequelize().QueryTypes.SELECT
|
|
175
|
-
}, options, { bind }));
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* A shortcut to prevent repeat insert
|
|
180
|
-
* @param tableName
|
|
181
|
-
* @param input
|
|
182
|
-
* @param uniqueCondition
|
|
183
|
-
* @param transaction
|
|
184
|
-
* @param options
|
|
185
|
-
*/
|
|
186
|
-
uniqueInsert({
|
|
187
|
-
tableName,
|
|
188
|
-
input,
|
|
189
|
-
uniqueCondition,
|
|
190
|
-
transaction
|
|
191
|
-
}, options = {}) {
|
|
192
|
-
const inputObj = Object.assign({}, input);
|
|
193
|
-
const typeAllowed = ['number', 'string', 'boolean'];
|
|
194
|
-
Object.entries(inputObj).forEach(p => {
|
|
195
|
-
const valType = typeof p[1];
|
|
196
|
-
//Allow null type here
|
|
197
|
-
if (typeAllowed.indexOf(valType) === -1 && p[1] !== null) {
|
|
198
|
-
throw new _exceptions.StandardException(`SQL inputObj ${p[0]}:${p[1]} with unsupported type ${valType}.`);
|
|
199
|
-
} else if (valType === 'boolean') {
|
|
200
|
-
if (p[1] === true) {
|
|
201
|
-
inputObj[p[0]] = 1;
|
|
202
|
-
} else {
|
|
203
|
-
inputObj[p[0]] = 0;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
const columns = Object.keys(inputObj);
|
|
208
|
-
const columnString = ['`', columns.join('`, `'), '`'].join('');
|
|
209
|
-
const valueString = Object.entries(inputObj).map(([key]) => `$${key} \`${key}\``).join(' , ');
|
|
210
|
-
const uniqueString = typeof uniqueCondition === 'string' ? uniqueCondition : [`SELECT * FROM ${tableName} WHERE `, this.getInstance().dialect.QueryGenerator.getWhereConditions(uniqueCondition)].join('');
|
|
211
|
-
/*
|
|
212
|
-
Original Example:
|
|
213
|
-
entities.getInstance().query(`INSERT INTO ${tableName}
|
|
214
|
-
(userId, status)
|
|
215
|
-
(
|
|
216
|
-
SELECT *
|
|
217
|
-
FROM (SELECT $userId userId, $status status) AS tmp
|
|
218
|
-
WHERE NOT EXISTS (
|
|
219
|
-
SELECT id FROM ${auditTable} WHERE userId = $userId AND status = 'pending'
|
|
220
|
-
) LIMIT 1
|
|
221
|
-
)`, { bind, transaction, type: entities.getSequelize().QueryTypes.INSERT });
|
|
222
|
-
*/
|
|
223
|
-
|
|
224
|
-
const sql = `INSERT INTO ${tableName}
|
|
225
|
-
(${columnString})
|
|
226
|
-
(
|
|
227
|
-
SELECT *
|
|
228
|
-
FROM (SELECT ${valueString}) AS tmp
|
|
229
|
-
WHERE NOT EXISTS (
|
|
230
|
-
${uniqueString} FOR UPDATE
|
|
231
|
-
) LIMIT 1
|
|
232
|
-
)`; //add FOR UPDATE to use eXclusive Lock
|
|
233
|
-
return this.getInstance().query(sql, Object.assign({
|
|
234
|
-
bind: inputObj,
|
|
235
|
-
transaction,
|
|
236
|
-
type: _sequelize2.default.QueryTypes.INSERT
|
|
237
|
-
}, options));
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* A short cut to start a database transaction
|
|
242
|
-
* @param options
|
|
243
|
-
*/
|
|
244
|
-
getTransaction(options = {}) {
|
|
245
|
-
return this.getInstance().transaction(Object.assign({
|
|
246
|
-
autocommit: true
|
|
247
|
-
}, options));
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* @returns {Sequelize}
|
|
252
|
-
*/
|
|
253
|
-
getSequelize() {
|
|
254
|
-
return _sequelize2.default;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* @returns {Sequelize}
|
|
259
|
-
*/
|
|
260
|
-
getInstance() {
|
|
261
|
-
this.init();
|
|
262
|
-
return this.sequelize;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* @param name
|
|
267
|
-
* @returns {Sequelize}
|
|
268
|
-
*/
|
|
269
|
-
get(name) {
|
|
270
|
-
this.init();
|
|
271
|
-
return this.entities[name];
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @returns {Object}
|
|
276
|
-
*/
|
|
277
|
-
getAll() {
|
|
278
|
-
this.init();
|
|
279
|
-
return this.entities;
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
exports.default = Entities;
|
|
283
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/entities/index.js"],"names":["Sequelize","prototype","validateIsUnique","col","msg","conditions","where","message","v","value","next","self","Model","describe","then","schema","Object","keys","filter","field","primaryKey","forEach","pk","$ne","count","found","catch","Entities","constructor","entitiesPath","sequelizeInstance","sequelize","entities","scanned","addTracer","options","logger","DI","get","assign","benchmark","logging","args","tracer","query","cost","pushed","queries","push","finishedAt","verbose","scan","withAssociate","fs","readdirSync","file","fileArray","split","indexOf","pop","entity","import","path","join","name","values","associate","init","getInstance","config","ns","isEnabled","cls","use","getContext","dbConfig","db","process","env","SEQUELIZE_REPLICATION_CONFIG_KEY","replication","database","util","isFunction","debug","sql","bind","type","getSequelize","QueryTypes","SELECT","uniqueInsert","tableName","input","uniqueCondition","transaction","inputObj","typeAllowed","entries","p","valType","StandardException","columns","columnString","valueString","map","key","uniqueString","dialect","QueryGenerator","getWhereConditions","INSERT","getTransaction","autocommit","getAll"],"mappings":"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","file":"index.js","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport assert from 'assert';\nimport cloneDeep from 'lodash/cloneDeep';\nimport Sequelize from 'sequelize';\nimport util from 'util';\nimport DI from '../di';\nimport { getMicroTimestamp } from '../utils';\nimport { StandardException } from '../exceptions';\n\n//From https://github.com/angelxmoreno/sequelize-isunique-validator\nSequelize.prototype.validateIsUnique = (col, msg) => {\n const conditions = { where: {} };\n const message = msg || `${col} must be unique`;\n return function v(value, next) {\n const self = this;\n this.Model.describe().then((schema) => {\n conditions.where[col] = value;\n Object\n .keys(schema)\n .filter(field => schema[field].primaryKey)\n .forEach((pk) => {\n conditions.where[pk] = { $ne: self[pk] };\n });\n }).then(() =>\n self.Model.count(conditions).then((found) => {\n if (found !== 0) {\n return next(message);\n }\n return next();\n })).catch(next);\n };\n};\n\n\nexport default class Entities {\n /**\n * @param {string} entitiesPath\n * @param {Sequelize|Function} sequelizeInstance\n */\n constructor(entitiesPath, sequelizeInstance = null) {\n this.entitiesPath = entitiesPath;\n this.sequelize = sequelizeInstance;\n this.entities = {};\n this.scanned = false;\n }\n\n /**\n * Add tracer info to end of SQL query logging\n * @param options\n * @returns {*}\n */\n static addTracer(options = {}) {\n const logger = DI.get('logger');\n return Object.assign(options, {\n benchmark: true,\n logging: (...args) => {\n const tracer = DI.get('namespace').get('tracer');\n const [query, cost] = args;\n let pushed = false;\n if (tracer && cost > 0) {\n tracer.queries.push({\n query,\n cost: cost * 1000,\n finishedAt: getMicroTimestamp()\n });\n pushed = true;\n }\n logger.verbose(...args, !pushed ? '| Tracer' : '');\n }\n });\n }\n\n /**\n * Scan all entity schemas under a special path\n * @param entitiesPath\n * @param withAssociate\n * @returns {Entities}\n */\n scan(entitiesPath, withAssociate = true) {\n assert(this.sequelize && this.sequelize instanceof Sequelize, 'Scan entities require a sequelize instance');\n\n fs\n .readdirSync(entitiesPath)\n .filter((file) => {\n const fileArray = file.split('.');\n return (file.indexOf('.') !== 0) &&\n (['js', 'es6'].indexOf(fileArray.pop()) !== -1) && (fileArray[0] !== 'index');\n })\n .forEach((file) => {\n const entity = this.sequelize.import(path.join(entitiesPath, file));\n this.entities[entity.name] = entity;\n });\n\n if (!withAssociate) {\n return this;\n }\n\n Object.values(this.entities).forEach((entity) => {\n if ('associate' in entity) {\n entity.associate(this.entities);\n }\n });\n return this;\n }\n\n /**\n * Init sequelize instance from DI config\n * @param withAssociate\n * @returns {*}\n */\n init(withAssociate = true) {\n if (this.sequelize && this.scanned) {\n return this.sequelize;\n }\n\n const logger = DI.get('logger').getInstance();\n if (!this.sequelize) {\n const config = DI.get('config').get();\n const ns = DI.get('namespace');\n if (ns.isEnabled()) {\n //Inject sequelize inner namespace, refer: http://docs.sequelizejs.com/en/latest/docs/transactions/\n Sequelize.cls = ns.use().getContext();\n }\n\n const dbConfig = cloneDeep(config.db);\n if (process.env.SEQUELIZE_REPLICATION_CONFIG_KEY) {\n dbConfig.replication = dbConfig[process.env.SEQUELIZE_REPLICATION_CONFIG_KEY];\n }\n this.sequelize = new Sequelize(\n config.db.database, null, null,\n Object.assign({}, config.sequelize, dbConfig, Entities.addTracer())\n );\n } else {\n this.sequelize = util.isFunction(this.sequelize) ? this.sequelize() : this.sequelize;\n }\n\n this.scan(this.entitiesPath, withAssociate);\n this.scanned = true;\n\n //TODO: mask password in logging\n logger.debug('Entities init by scanned %s, Replication: %j', this.entitiesPath, this.sequelize.options.replication);\n return this;\n }\n\n /**\n * Shortcut for Sequelize query\n * @param sql\n * @param bind\n * @param options\n * @returns {*|{foo}|{}}\n */\n query(sql, bind = {}, options = {}) {\n return this.getInstance().query(sql, Object.assign({\n type: this.getSequelize().QueryTypes.SELECT\n }, options, { bind }));\n }\n\n /**\n * A shortcut to prevent repeat insert\n * @param tableName\n * @param input\n * @param uniqueCondition\n * @param transaction\n * @param options\n */\n uniqueInsert({\n tableName,\n input,\n uniqueCondition,\n transaction\n }, options = {}) {\n const inputObj = Object.assign({}, input);\n const typeAllowed = ['number', 'string', 'boolean'];\n Object.entries(inputObj).forEach((p) => {\n const valType = typeof p[1];\n //Allow null type here\n if (typeAllowed.indexOf(valType) === -1 && p[1] !== null) {\n throw new StandardException(`SQL inputObj ${p[0]}:${p[1]} with unsupported type ${valType}.`);\n } else if (valType === 'boolean') {\n if (p[1] === true) {\n inputObj[p[0]] = 1;\n } else {\n inputObj[p[0]] = 0;\n }\n }\n });\n const columns = Object.keys(inputObj);\n const columnString = ['`', columns.join('`, `'), '`'].join('');\n const valueString = Object.entries(inputObj).map(([key]) => `$${key} \\`${key}\\``).join(' , ');\n const uniqueString = typeof uniqueCondition === 'string' ? uniqueCondition :\n [`SELECT * FROM ${tableName} WHERE `, this.getInstance().dialect.QueryGenerator.getWhereConditions(uniqueCondition)].join('');\n /*\n Original Example:\n entities.getInstance().query(`INSERT INTO ${tableName}\n (userId, status)\n (\n SELECT *\n FROM (SELECT $userId userId, $status status) AS tmp\n WHERE NOT EXISTS (\n SELECT id FROM ${auditTable} WHERE userId = $userId AND status = 'pending'\n ) LIMIT 1\n )`, { bind, transaction, type: entities.getSequelize().QueryTypes.INSERT });\n */\n\n const sql = `INSERT INTO ${tableName} \n (${columnString}) \n (\n SELECT *\n FROM (SELECT ${valueString}) AS tmp\n WHERE NOT EXISTS (\n ${uniqueString} FOR UPDATE\n ) LIMIT 1\n )`; //add FOR UPDATE to use eXclusive Lock\n return this.getInstance().query(sql, Object.assign({\n bind: inputObj,\n transaction,\n type: Sequelize.QueryTypes.INSERT\n }, options));\n }\n\n /**\n * A short cut to start a database transaction\n * @param options\n */\n getTransaction(options = {}) {\n return this.getInstance().transaction(Object.assign({\n autocommit: true\n }, options));\n }\n\n /**\n * @returns {Sequelize}\n */\n getSequelize() {\n return Sequelize;\n }\n\n /**\n * @returns {Sequelize}\n */\n getInstance() {\n this.init();\n return this.sequelize;\n }\n\n /**\n * @param name\n * @returns {Sequelize}\n */\n get(name) {\n this.init();\n return this.entities[name];\n }\n\n /**\n * @returns {Object}\n */\n getAll() {\n this.init();\n return this.entities;\n }\n}\n"]}
|