evaengine 0.11.2 → 1.0.1
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/commands/index.js +12 -0
- package/{lib → src}/commands/interface.js +5 -11
- package/src/commands/make_entity.js +490 -0
- package/src/commands/tramp.js +34 -0
- package/{lib → src}/config/index.js +7 -9
- package/{lib → src}/di.js +11 -26
- package/src/engine.js +551 -0
- package/{lib → src}/entities/index.js +72 -82
- package/{lib → src}/exceptions/index.js +71 -92
- package/src/index.js +57 -0
- package/src/middlewares/auth.js +67 -0
- package/src/middlewares/auth_kong.js +28 -0
- package/src/middlewares/debug.js +88 -0
- package/src/middlewares/index.js +18 -0
- package/src/middlewares/providers.js +73 -0
- package/src/middlewares/session.js +58 -0
- package/{lib → src}/middlewares/trace.js +74 -86
- package/src/middlewares/validator.js +50 -0
- package/src/middlewares/view_cache.js +127 -0
- package/{lib → src}/services/cache.js +45 -56
- package/src/services/config.js +111 -0
- package/src/services/env.js +28 -0
- package/src/services/event_manager.js +84 -0
- package/src/services/http_client.js +160 -0
- package/src/services/index.js +27 -0
- package/src/services/interface.js +5 -0
- package/src/services/joi.js +13 -0
- package/src/services/jwt_token.js +89 -0
- package/src/services/jwt_token_kong.js +75 -0
- package/src/services/logger.js +148 -0
- package/src/services/namespace.js +176 -0
- package/src/services/now.js +49 -0
- package/src/services/providers.js +158 -0
- package/src/services/redis.js +55 -0
- package/src/services/rest_client.js +112 -0
- package/src/swagger/index.js +668 -0
- package/{lib → src}/utils/api_scaffold.js +26 -39
- package/src/utils/case_converter.js +33 -0
- package/src/utils/crc32.js +44 -0
- package/src/utils/datetime.js +13 -0
- package/src/utils/host.js +39 -0
- package/src/utils/index.js +35 -0
- package/{lib → src}/utils/pagination.js +22 -31
- package/src/utils/random.js +23 -0
- package/{lib → src}/utils/smart_query.js +27 -27
- package/src/utils/test.js +48 -0
- package/src/utils/wrapper.js +8 -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.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.map +0 -1
- 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.map +0 -1
- 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.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.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.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.map +0 -1
- package/lib/utils/random.js +0 -33
- package/lib/utils/random.js.map +0 -1
- 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
|
@@ -1,35 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var _constitute = require('constitute');
|
|
11
|
-
|
|
12
|
-
var _exceptions = require('./../exceptions');
|
|
13
|
-
|
|
14
|
-
var _redis = require('./redis');
|
|
15
|
-
|
|
16
|
-
var _redis2 = _interopRequireDefault(_redis);
|
|
17
|
-
|
|
18
|
-
var _di = require('./../di');
|
|
19
|
-
|
|
20
|
-
var _di2 = _interopRequireDefault(_di);
|
|
21
|
-
|
|
22
|
-
var _config = require('./config');
|
|
23
|
-
|
|
24
|
-
var _config2 = _interopRequireDefault(_config);
|
|
25
|
-
|
|
26
|
-
var _interface = require('./interface');
|
|
27
|
-
|
|
28
|
-
var _interface2 = _interopRequireDefault(_interface);
|
|
29
|
-
|
|
30
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
|
-
|
|
32
|
-
let Store = exports.Store = class Store {
|
|
1
|
+
import constitute from 'constitute';
|
|
2
|
+
import { OperationUnsupportedException } from './../exceptions/index.js';
|
|
3
|
+
import Redis from './redis.js';
|
|
4
|
+
import DI from './../di.js';
|
|
5
|
+
import Config from './config.js';
|
|
6
|
+
import ServiceInterface from './interface.js';
|
|
7
|
+
|
|
8
|
+
export class Store {
|
|
33
9
|
getInstance() {
|
|
34
10
|
return this;
|
|
35
11
|
}
|
|
@@ -55,10 +31,11 @@ let Store = exports.Store = class Store {
|
|
|
55
31
|
}
|
|
56
32
|
|
|
57
33
|
tags() {
|
|
58
|
-
throw new
|
|
34
|
+
throw new OperationUnsupportedException('Not support tag feature');
|
|
59
35
|
}
|
|
60
|
-
}
|
|
61
|
-
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class NullStore extends Store {
|
|
62
39
|
namespace() {
|
|
63
40
|
return this;
|
|
64
41
|
}
|
|
@@ -66,8 +43,9 @@ let NullStore = exports.NullStore = class NullStore extends Store {
|
|
|
66
43
|
tags() {
|
|
67
44
|
return this;
|
|
68
45
|
}
|
|
69
|
-
}
|
|
70
|
-
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class RedisNamespaceStore extends Store {
|
|
71
49
|
constructor(prefix, namespace, redis) {
|
|
72
50
|
super();
|
|
73
51
|
this.prefix = prefix;
|
|
@@ -96,7 +74,10 @@ let RedisNamespaceStore = exports.RedisNamespaceStore = class RedisNamespaceStor
|
|
|
96
74
|
}
|
|
97
75
|
|
|
98
76
|
set(key, value, minutes, mutex) {
|
|
99
|
-
const args = [
|
|
77
|
+
const args = [
|
|
78
|
+
this.key(key),
|
|
79
|
+
JSON.stringify(value)
|
|
80
|
+
];
|
|
100
81
|
if (minutes) {
|
|
101
82
|
args.push('ex', minutes * 60);
|
|
102
83
|
}
|
|
@@ -110,20 +91,22 @@ let RedisNamespaceStore = exports.RedisNamespaceStore = class RedisNamespaceStor
|
|
|
110
91
|
}
|
|
111
92
|
|
|
112
93
|
flush() {
|
|
113
|
-
return this.redis.keys([this.prefix, this.namespace, '*'].join(':'))
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
94
|
+
return this.redis.keys([this.prefix, this.namespace, '*'].join(':'))
|
|
95
|
+
.then((keys) => {
|
|
96
|
+
if (keys.length) {
|
|
97
|
+
return this.redis.del(keys);
|
|
98
|
+
}
|
|
99
|
+
return 0;
|
|
100
|
+
});
|
|
119
101
|
}
|
|
120
|
-
}
|
|
121
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export class RedisStore extends Store {
|
|
122
105
|
constructor(prefix, redis) {
|
|
123
106
|
super();
|
|
124
107
|
this.prefix = prefix;
|
|
125
108
|
this.namespaceHandler = {};
|
|
126
|
-
this.redis = redis ||
|
|
109
|
+
this.redis = redis || DI.get('redis').getInstance();
|
|
127
110
|
}
|
|
128
111
|
|
|
129
112
|
getInstance() {
|
|
@@ -155,7 +138,10 @@ let RedisStore = exports.RedisStore = class RedisStore extends Store {
|
|
|
155
138
|
}
|
|
156
139
|
|
|
157
140
|
set(key, value, minutes, mutex) {
|
|
158
|
-
const args = [
|
|
141
|
+
const args = [
|
|
142
|
+
this.key(key),
|
|
143
|
+
JSON.stringify(value)
|
|
144
|
+
];
|
|
159
145
|
if (minutes) {
|
|
160
146
|
args.push('ex', minutes * 60);
|
|
161
147
|
}
|
|
@@ -171,9 +157,9 @@ let RedisStore = exports.RedisStore = class RedisStore extends Store {
|
|
|
171
157
|
flush() {
|
|
172
158
|
return this.redis.flushall();
|
|
173
159
|
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
class Cache extends ServiceInterface {
|
|
177
163
|
constructor(config) {
|
|
178
164
|
super();
|
|
179
165
|
this.config = config.get('cache');
|
|
@@ -182,7 +168,7 @@ let Cache = (_dec = (0, _constitute.Dependencies)(_config2.default, _redis2.defa
|
|
|
182
168
|
this.store = null;
|
|
183
169
|
}
|
|
184
170
|
|
|
185
|
-
|
|
171
|
+
setStore(store) {
|
|
186
172
|
this.store = store;
|
|
187
173
|
return this;
|
|
188
174
|
}
|
|
@@ -194,7 +180,8 @@ let Cache = (_dec = (0, _constitute.Dependencies)(_config2.default, _redis2.defa
|
|
|
194
180
|
if (this.store) {
|
|
195
181
|
return this.store;
|
|
196
182
|
}
|
|
197
|
-
this.store = this.driver === 'redis' ?
|
|
183
|
+
this.store = this.driver === 'redis' ?
|
|
184
|
+
new RedisStore(this.prefix) : new NullStore(this.prefix);
|
|
198
185
|
return this.store;
|
|
199
186
|
}
|
|
200
187
|
|
|
@@ -229,6 +216,8 @@ let Cache = (_dec = (0, _constitute.Dependencies)(_config2.default, _redis2.defa
|
|
|
229
216
|
flush() {
|
|
230
217
|
return this.getStore().flush();
|
|
231
218
|
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
constitute.Dependencies(Config, Redis)(Cache);
|
|
222
|
+
export default Cache;
|
|
223
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import constitute from 'constitute';
|
|
4
|
+
import * as springConfigClient from 'cloud-config-client';
|
|
5
|
+
import Env from './env.js';
|
|
6
|
+
import EngineConfig from '../config/index.js';
|
|
7
|
+
import ServiceInterface from './interface.js';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
class Config extends ServiceInterface {
|
|
12
|
+
/**
|
|
13
|
+
* @param env {Env}
|
|
14
|
+
*/
|
|
15
|
+
constructor(env) {
|
|
16
|
+
super();
|
|
17
|
+
this.env = env;
|
|
18
|
+
this.path = null;
|
|
19
|
+
this.mergedFiles = [];
|
|
20
|
+
this.config = null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setPath(path) {
|
|
24
|
+
this.path = path;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve configurations from Spring Cloud Config Server.
|
|
30
|
+
* @param endpoint
|
|
31
|
+
* @param name
|
|
32
|
+
* @param profiles
|
|
33
|
+
* @param label
|
|
34
|
+
* @returns {Promise.<void>}
|
|
35
|
+
*/
|
|
36
|
+
async resolveSpringConfig({
|
|
37
|
+
endpoint,
|
|
38
|
+
name,
|
|
39
|
+
profiles,
|
|
40
|
+
label = 'master'
|
|
41
|
+
}) {
|
|
42
|
+
if (!this.config) {
|
|
43
|
+
this.config = this.loadConfigFromFiles();
|
|
44
|
+
}
|
|
45
|
+
const configRemote = await springConfigClient.load({
|
|
46
|
+
endpoint,
|
|
47
|
+
name,
|
|
48
|
+
profiles: _.isString(profiles) ? profiles.split(',') : [],
|
|
49
|
+
label
|
|
50
|
+
});
|
|
51
|
+
configRemote.forEach((key, value) => {
|
|
52
|
+
_.set(this.config, key, value);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get(key) {
|
|
57
|
+
if (this.config) {
|
|
58
|
+
return key ? Config.search(key, this.config) : this.config;
|
|
59
|
+
}
|
|
60
|
+
this.config = this.loadConfigFromFiles();
|
|
61
|
+
return key ? Config.search(key, this.config) : this.config;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
loadConfigFromFiles() {
|
|
65
|
+
const env = this.env.get();
|
|
66
|
+
const configPath = this.path;
|
|
67
|
+
const pathDefault = `${configPath}/config.default.cjs`;
|
|
68
|
+
const pathEnv = `${configPath}/config.${env}.cjs`;
|
|
69
|
+
const pathLocal = `${configPath}/config.local.${env}.cjs`;
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const configDefault = require(pathDefault);
|
|
73
|
+
this.mergedFiles.push(pathDefault);
|
|
74
|
+
const configEnv = require(pathEnv);
|
|
75
|
+
this.mergedFiles.push(pathEnv);
|
|
76
|
+
let configLocal = {};
|
|
77
|
+
try {
|
|
78
|
+
configLocal = require(pathLocal);
|
|
79
|
+
this.mergedFiles.push(pathLocal);
|
|
80
|
+
} catch {
|
|
81
|
+
configLocal = {};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
return _.merge({}, EngineConfig, configDefault, configEnv, configLocal);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getMergedFiles() {
|
|
89
|
+
return this.mergedFiles;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
reload() {
|
|
93
|
+
this.config = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} keyString
|
|
98
|
+
* @param {Object} target
|
|
99
|
+
* @returns {*}
|
|
100
|
+
*/
|
|
101
|
+
static search(keyString, target) {
|
|
102
|
+
if (typeof keyString !== 'string') {
|
|
103
|
+
return target;
|
|
104
|
+
}
|
|
105
|
+
return _.get(target, keyString);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
constitute.Dependencies(Env)(Config);
|
|
110
|
+
export default Config;
|
|
111
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import ServiceInterface from './interface.js';
|
|
2
|
+
|
|
3
|
+
let env = null;
|
|
4
|
+
export const TYPES = {
|
|
5
|
+
PRODUCTION: 'production',
|
|
6
|
+
TEST: 'test',
|
|
7
|
+
DEVELOPMENT: 'development'
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default class Env extends ServiceInterface {
|
|
11
|
+
get() {
|
|
12
|
+
env = [TYPES.PRODUCTION, TYPES.TEST, TYPES.DEVELOPMENT].indexOf(process.env.NODE_ENV) > -1
|
|
13
|
+
? process.env.NODE_ENV : TYPES.DEVELOPMENT;
|
|
14
|
+
return env;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
isTest() {
|
|
18
|
+
return this.get() === TYPES.TEST;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
isProduction() {
|
|
22
|
+
return this.get() === TYPES.PRODUCTION;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
isDevelopment() {
|
|
26
|
+
return this.get() === TYPES.DEVELOPMENT;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import constitute from 'constitute';
|
|
2
|
+
import EventEmitter from 'events';
|
|
3
|
+
import camelCase from 'lodash/camelCase.js';
|
|
4
|
+
import { RuntimeException } from '../exceptions/index.js';
|
|
5
|
+
import Logger from './logger.js';
|
|
6
|
+
import ServiceInterface from './interface.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A strict version of EventEmitter
|
|
10
|
+
* 1. listener must be a standard class
|
|
11
|
+
* 2. unregistered event not allow to emit
|
|
12
|
+
* 3. all events register and trigger will be recorded
|
|
13
|
+
*/
|
|
14
|
+
class EventManager extends ServiceInterface {
|
|
15
|
+
constructor(logger) {
|
|
16
|
+
super();
|
|
17
|
+
this.logger = logger;
|
|
18
|
+
this.emitter = new EventEmitter();
|
|
19
|
+
this.events = new Set();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getProto() {
|
|
23
|
+
return EventEmitter;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getAllowEvents() {
|
|
27
|
+
return this.events;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getEmitter() {
|
|
31
|
+
//TODO: 屏蔽写入
|
|
32
|
+
return this.emitter;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Allow to register a class such like
|
|
37
|
+
* class Foo { get prefix(){ return 'foo'} get actions() { return ['bar']} }
|
|
38
|
+
* @param ListenerClass
|
|
39
|
+
* @returns {EventManager}
|
|
40
|
+
*/
|
|
41
|
+
addListener(ListenerClass) {
|
|
42
|
+
if (typeof ListenerClass !== 'function') {
|
|
43
|
+
throw new RuntimeException('Not a standard listener input');
|
|
44
|
+
}
|
|
45
|
+
const listener = new ListenerClass();
|
|
46
|
+
const { prefix, actions } = listener;
|
|
47
|
+
if (!prefix || !actions) {
|
|
48
|
+
throw new RuntimeException('Not a standard listener input');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const events = {};
|
|
52
|
+
const eventsCount = this.events.size;
|
|
53
|
+
for (const action of actions) {
|
|
54
|
+
events[[prefix, action, 'before'].join(':')] = camelCase(['before', action].join('_'));
|
|
55
|
+
events[[prefix, action, 'after'].join(':')] = camelCase(['after', action].join('_'));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//TODO: 用Set保存注册的事件
|
|
59
|
+
for (const [eventName, callback] of Object.entries(events)) {
|
|
60
|
+
this.events.add(eventName);
|
|
61
|
+
if (Reflect.has(listener, callback) === false) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
this.emitter.addListener(eventName, listener[callback]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (eventsCount + Object.keys(events).length !== this.events.size) {
|
|
68
|
+
throw new RuntimeException('Repeated event name has been registered, please check');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// this.logger.debug('Registered events', this.emitter.eventNames());
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
emit(eventName, callback) {
|
|
76
|
+
if (!this.events.has(eventName)) {
|
|
77
|
+
throw new RuntimeException(`Event ${eventName} not registered yet`);
|
|
78
|
+
}
|
|
79
|
+
return this.emitter.emit(eventName, callback);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
constitute.Dependencies(Logger)(EventManager);
|
|
84
|
+
export default EventManager;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import constitute from 'constitute';
|
|
2
|
+
import request from 'request-promise-native';
|
|
3
|
+
import Config from './config.js';
|
|
4
|
+
import Logger from './logger.js';
|
|
5
|
+
import { HttpRequestLogicException, HttpRequestIOException } from '../exceptions/index.js';
|
|
6
|
+
import ServiceInterface from './interface.js';
|
|
7
|
+
|
|
8
|
+
export const deepClone = obj =>
|
|
9
|
+
JSON.parse(JSON.stringify(obj));
|
|
10
|
+
|
|
11
|
+
const TOO_LONG_BODY = '____TLDR____';
|
|
12
|
+
|
|
13
|
+
let debugFlag = false;
|
|
14
|
+
/* eslint-disable */
|
|
15
|
+
//Mod version of https://github.com/request/request-debug
|
|
16
|
+
export const requestDebug = (logger, maxBodyLength = process.env.MAX_REQUEST_DEBUG_BODY || 3000) => {
|
|
17
|
+
if (debugFlag === true) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let proto = {};
|
|
22
|
+
let debugId = 0;
|
|
23
|
+
if (request.Request) {
|
|
24
|
+
proto = request.Request.prototype;
|
|
25
|
+
} else if (request.get && request.post) {
|
|
26
|
+
// The object returned by request.defaults() doesn't include the
|
|
27
|
+
// Request property, so do this horrible thing to get at it. Per
|
|
28
|
+
// Wikipedia, port 4 is unassigned.
|
|
29
|
+
const req = request('http://localhost:4').on('error', () => {
|
|
30
|
+
});
|
|
31
|
+
proto = req.constructor.prototype;
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error('Pass the object returned by require("request") to this function.');
|
|
34
|
+
}
|
|
35
|
+
if (proto._initBeforeDebug) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
proto._initBeforeDebug = proto.init;
|
|
40
|
+
|
|
41
|
+
const ignoreDebug = (headers) => {
|
|
42
|
+
if (!headers || Object.keys(headers).length < 1) {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
return Object.keys(headers)
|
|
46
|
+
.filter(key => !key.startsWith('x-debug'))
|
|
47
|
+
.reduce((res, key) => (res[key] = headers[key], res), {});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
proto.init = function () {
|
|
51
|
+
if (this._debugId) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.on('request', function (req) {
|
|
55
|
+
const data = {
|
|
56
|
+
headers: deepClone(this.headers)
|
|
57
|
+
};
|
|
58
|
+
if (this.body) {
|
|
59
|
+
data.body = maxBodyLength > 0 && this.body.toString().length < maxBodyLength ? this.body.toString('utf8') : TOO_LONG_BODY;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
logger.verbose('[HTTP_REQUEST_%s] [%s %s] [REQ_HEADERS: %s] [REQ_BODY: %s]', this._debugId,
|
|
63
|
+
this.method.toUpperCase(), this.uri.href, JSON.stringify(data.headers), data.body || ''
|
|
64
|
+
);
|
|
65
|
+
}).on('response', function (res) {
|
|
66
|
+
if (this.callback) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const bodyLength = res.headers['content-length'] || (res.body ? res.body.toString().length : 0);
|
|
71
|
+
logger.verbose('[HTTP_RESPONSE_%s] [%s %s] [%s] [RES_HEADERS: %s] [RES_BODY: %s]', this._debugId,
|
|
72
|
+
this.method.toUpperCase(), this.uri.href, res.statusCode, JSON.stringify(ignoreDebug(res.headers)),
|
|
73
|
+
bodyLength > maxBodyLength ? TOO_LONG_BODY : res.body || ''
|
|
74
|
+
);
|
|
75
|
+
}).on('complete', function (res) {
|
|
76
|
+
if (!this.callback) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const bodyLength = res.headers['content-length'] || (res.body ? res.body.toString().length : 0);
|
|
81
|
+
logger.verbose('[HTTP_RESPONSE_%s] [%s %s] [%s] [RES_HEADERS: %s] [RES_BODY: %s]', this._debugId,
|
|
82
|
+
this.method.toUpperCase(), this.uri.href, res.statusCode, JSON.stringify(ignoreDebug(res.headers)),
|
|
83
|
+
bodyLength > maxBodyLength ? TOO_LONG_BODY : res.body || ''
|
|
84
|
+
);
|
|
85
|
+
}).on('redirect', function () {
|
|
86
|
+
|
|
87
|
+
logger.verbose('[HTTP_REDIRECT_%s] [%s %s] [%s] [RES_HEADERS: %s] [RES_BODY: %s]', this._debugId,
|
|
88
|
+
this.method.toUpperCase(), this.uri.href, this.response.statusCode, JSON.stringify(ignoreDebug(this.response.headers)), '');
|
|
89
|
+
});
|
|
90
|
+
this._debugId = ++debugId;
|
|
91
|
+
return proto._initBeforeDebug.apply(this, arguments);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
debugFlag = true;
|
|
95
|
+
};
|
|
96
|
+
/* eslint-enable */
|
|
97
|
+
|
|
98
|
+
class HttpClient extends ServiceInterface {
|
|
99
|
+
/**
|
|
100
|
+
* @param config {Config}
|
|
101
|
+
* @param logger {Logger}
|
|
102
|
+
*/
|
|
103
|
+
constructor(config, logger) {
|
|
104
|
+
super();
|
|
105
|
+
this.config = config.get();
|
|
106
|
+
this.client = request;
|
|
107
|
+
requestDebug(logger);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getProto() {
|
|
111
|
+
return request;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getInstance() {
|
|
115
|
+
return this.client;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async request(params) {
|
|
119
|
+
try {
|
|
120
|
+
return await this.client(params);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
const { statusCode } = e;
|
|
123
|
+
if (statusCode && statusCode >= 400 && statusCode < 500) {
|
|
124
|
+
throw new HttpRequestLogicException(e);
|
|
125
|
+
}
|
|
126
|
+
throw new HttpRequestIOException(e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
dumpRequest(req, asString = false) {
|
|
131
|
+
const getBody = (r) => {
|
|
132
|
+
if (r._json) {
|
|
133
|
+
return r.body;
|
|
134
|
+
}
|
|
135
|
+
return r.form(r.formData).body;
|
|
136
|
+
};
|
|
137
|
+
const dump = {
|
|
138
|
+
method: req.method,
|
|
139
|
+
protocol: req.uri && req.uri.protocol === 'https:' ? 'https' : 'http',
|
|
140
|
+
url: req.uri ? req.uri.href : null,
|
|
141
|
+
headers: req.headers,
|
|
142
|
+
body: req.req && (req._json || req.formData)
|
|
143
|
+
? getBody(req) : null
|
|
144
|
+
};
|
|
145
|
+
return asString === true ? JSON.stringify(dump) : dump;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
dumpResponse(res, asString = false) {
|
|
149
|
+
const dump = {
|
|
150
|
+
statusCode: res.statusCode,
|
|
151
|
+
statusMessage: res.statusMessage,
|
|
152
|
+
headers: res.headers,
|
|
153
|
+
body: res.body
|
|
154
|
+
};
|
|
155
|
+
return asString === true ? JSON.stringify(dump) : dump;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
constitute.Dependencies(Config, Logger)(HttpClient);
|
|
160
|
+
export default HttpClient;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Cache from './cache.js';
|
|
2
|
+
import Config from './config.js';
|
|
3
|
+
import Env from './env.js';
|
|
4
|
+
import HttpClient from './http_client.js';
|
|
5
|
+
import JsonWebToken from './jwt_token.js';
|
|
6
|
+
import Logger from './logger.js';
|
|
7
|
+
import Redis from './redis.js';
|
|
8
|
+
import RestClient from './rest_client.js';
|
|
9
|
+
import Namespace from './namespace.js';
|
|
10
|
+
import Now from './now.js';
|
|
11
|
+
import ValidatorBase from './joi.js';
|
|
12
|
+
import EventManager from './event_manager.js';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
Cache,
|
|
16
|
+
Config,
|
|
17
|
+
Env,
|
|
18
|
+
HttpClient,
|
|
19
|
+
JsonWebToken,
|
|
20
|
+
Logger,
|
|
21
|
+
Redis,
|
|
22
|
+
RestClient,
|
|
23
|
+
Namespace,
|
|
24
|
+
Now,
|
|
25
|
+
ValidatorBase,
|
|
26
|
+
EventManager
|
|
27
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import constitute from 'constitute';
|
|
2
|
+
import jwt from 'jwt-simple';
|
|
3
|
+
import Config from './config.js';
|
|
4
|
+
import Redis from './redis.js';
|
|
5
|
+
import ServiceInterface from './interface.js';
|
|
6
|
+
|
|
7
|
+
class JsonWebToken extends ServiceInterface {
|
|
8
|
+
/**
|
|
9
|
+
* @param config {Config}
|
|
10
|
+
* @param redis {Redis}
|
|
11
|
+
*/
|
|
12
|
+
constructor(config, redis) {
|
|
13
|
+
super();
|
|
14
|
+
this.redis = redis.getInstance();
|
|
15
|
+
this.config = config.get('token');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getProto() {
|
|
19
|
+
return jwt;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getRedis() {
|
|
23
|
+
return this.redis;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getPrefix() {
|
|
27
|
+
return this.config.prefix;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async save(uid, item) {
|
|
31
|
+
const toSaveItem = Object.assign({ uid }, item);
|
|
32
|
+
const tokenString = this.encode(toSaveItem);
|
|
33
|
+
const key = [this.getPrefix(), uid, tokenString.split('.').pop()].join(':');
|
|
34
|
+
//TODO 过期时间
|
|
35
|
+
await this.getRedis().set(key, JSON.stringify(toSaveItem));
|
|
36
|
+
return tokenString;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async find(tokenString) {
|
|
40
|
+
if (!tokenString) {
|
|
41
|
+
return { uid: null, expiredAt: 0 };
|
|
42
|
+
}
|
|
43
|
+
const parsedToken = this.decode(tokenString);
|
|
44
|
+
if (!parsedToken || !{}.hasOwnProperty.call(parsedToken, 'uid')) {
|
|
45
|
+
return { uid: null, expiredAt: 0 };
|
|
46
|
+
}
|
|
47
|
+
const key = [this.getPrefix(), parsedToken.uid, tokenString.split('.').pop()].join(':');
|
|
48
|
+
const storedToken = await this.redis.get(key);
|
|
49
|
+
if (!storedToken) {
|
|
50
|
+
return {
|
|
51
|
+
uid: parsedToken.uid,
|
|
52
|
+
expiredAt: 0
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return JSON.parse(storedToken);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
clear(tokenString) {
|
|
59
|
+
if (!tokenString) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const key = this.getRedisKey(tokenString);
|
|
63
|
+
if (!key) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return this.redis.del(key);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getRedisKey(tokenString, groupOnly = false) {
|
|
70
|
+
const parsedToken = this.decode(tokenString);
|
|
71
|
+
if (!parsedToken || !{}.hasOwnProperty.call(parsedToken, 'uid')) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
return groupOnly === true ?
|
|
75
|
+
[this.getPrefix(), parsedToken.uid].join(':') :
|
|
76
|
+
[this.getPrefix(), parsedToken.uid, tokenString.split('.').pop()].join(':');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
encode(item, secret = this.config.secret) {
|
|
80
|
+
return jwt.encode(item, secret);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
decode(str, secret = this.config.secret) {
|
|
84
|
+
return jwt.decode(str, secret);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
constitute.Dependencies(Config, Redis)(JsonWebToken);
|
|
89
|
+
export default JsonWebToken;
|