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.
Files changed (105) hide show
  1. package/.ai/analysis.md +657 -0
  2. package/.ai/architecture/runtime.md +504 -0
  3. package/.ai/contracts/public-api.md +447 -0
  4. package/.ai/external-project-guide.md +248 -0
  5. package/.ai/vision.md +314 -0
  6. package/README.md +51 -62
  7. package/bin/engine +15 -21
  8. package/index.js +2 -18
  9. package/package.json +60 -64
  10. package/src/index.js +57 -0
  11. package/bin/engine-babel +0 -38
  12. package/lib/commands/index.js +0 -25
  13. package/lib/commands/index.js.map +0 -1
  14. package/lib/commands/interface.js +0 -51
  15. package/lib/commands/interface.js.map +0 -1
  16. package/lib/commands/make_entity.js +0 -549
  17. package/lib/commands/make_entity.js.map +0 -1
  18. package/lib/commands/tramp.js +0 -53
  19. package/lib/commands/tramp.js.map +0 -1
  20. package/lib/config/index.js +0 -98
  21. package/lib/config/index.js.map +0 -1
  22. package/lib/di.js +0 -99
  23. package/lib/di.js.map +0 -1
  24. package/lib/engine.js +0 -558
  25. package/lib/engine.js.map +0 -1
  26. package/lib/entities/index.js +0 -283
  27. package/lib/entities/index.js.map +0 -1
  28. package/lib/exceptions/index.js +0 -522
  29. package/lib/exceptions/index.js.map +0 -1
  30. package/lib/index.js +0 -105
  31. package/lib/index.js.map +0 -1
  32. package/lib/middlewares/auth.js +0 -97
  33. package/lib/middlewares/auth.js.map +0 -1
  34. package/lib/middlewares/auth_kong.js +0 -48
  35. package/lib/middlewares/auth_kong.js.map +0 -1
  36. package/lib/middlewares/debug.js +0 -68
  37. package/lib/middlewares/debug.js.map +0 -1
  38. package/lib/middlewares/index.js +0 -45
  39. package/lib/middlewares/index.js.map +0 -1
  40. package/lib/middlewares/providers.js +0 -102
  41. package/lib/middlewares/providers.js.map +0 -1
  42. package/lib/middlewares/session.js +0 -76
  43. package/lib/middlewares/session.js.map +0 -1
  44. package/lib/middlewares/trace.js +0 -241
  45. package/lib/middlewares/trace.js.map +0 -1
  46. package/lib/middlewares/validator.js +0 -71
  47. package/lib/middlewares/validator.js.map +0 -1
  48. package/lib/middlewares/view_cache.js +0 -160
  49. package/lib/middlewares/view_cache.js.map +0 -1
  50. package/lib/services/cache.js +0 -234
  51. package/lib/services/cache.js.map +0 -1
  52. package/lib/services/config.js +0 -140
  53. package/lib/services/config.js.map +0 -1
  54. package/lib/services/env.js +0 -40
  55. package/lib/services/env.js.map +0 -1
  56. package/lib/services/event_manager.js +0 -110
  57. package/lib/services/event_manager.js.map +0 -1
  58. package/lib/services/http_client.js +0 -178
  59. package/lib/services/http_client.js.map +0 -1
  60. package/lib/services/index.js +0 -70
  61. package/lib/services/index.js.map +0 -1
  62. package/lib/services/interface.js +0 -12
  63. package/lib/services/interface.js.map +0 -1
  64. package/lib/services/joi.js +0 -28
  65. package/lib/services/joi.js.map +0 -1
  66. package/lib/services/jwt_token.js +0 -120
  67. package/lib/services/jwt_token.js.map +0 -1
  68. package/lib/services/jwt_token_kong.js +0 -111
  69. package/lib/services/jwt_token_kong.js.map +0 -1
  70. package/lib/services/logger.js +0 -172
  71. package/lib/services/logger.js.map +0 -1
  72. package/lib/services/namespace.js +0 -188
  73. package/lib/services/namespace.js.map +0 -1
  74. package/lib/services/now.js +0 -69
  75. package/lib/services/now.js.map +0 -1
  76. package/lib/services/providers.js +0 -195
  77. package/lib/services/providers.js.map +0 -1
  78. package/lib/services/redis.js +0 -77
  79. package/lib/services/redis.js.map +0 -1
  80. package/lib/services/rest_client.js +0 -136
  81. package/lib/services/rest_client.js.map +0 -1
  82. package/lib/swagger/index.js +0 -684
  83. package/lib/swagger/index.js.map +0 -1
  84. package/lib/utils/api_scaffold.js +0 -253
  85. package/lib/utils/api_scaffold.js.map +0 -1
  86. package/lib/utils/case_converter.js +0 -48
  87. package/lib/utils/case_converter.js.map +0 -1
  88. package/lib/utils/crc32.js +0 -22
  89. package/lib/utils/crc32.js.map +0 -1
  90. package/lib/utils/datetime.js +0 -21
  91. package/lib/utils/datetime.js.map +0 -1
  92. package/lib/utils/host.js +0 -48
  93. package/lib/utils/host.js.map +0 -1
  94. package/lib/utils/index.js +0 -61
  95. package/lib/utils/index.js.map +0 -1
  96. package/lib/utils/pagination.js +0 -269
  97. package/lib/utils/pagination.js.map +0 -1
  98. package/lib/utils/random.js +0 -33
  99. package/lib/utils/random.js.map +0 -1
  100. package/lib/utils/smart_query.js +0 -342
  101. package/lib/utils/smart_query.js.map +0 -1
  102. package/lib/utils/test.js +0 -62
  103. package/lib/utils/test.js.map +0 -1
  104. package/lib/utils/wrapper.js +0 -9
  105. package/lib/utils/wrapper.js.map +0 -1
@@ -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"]}