@zerooneit/expressive-tea 1.2.3 → 1.3.0-beta.2
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/.circleci/config.yml +9 -0
- package/README.md +70 -88
- package/classes/Boot.d.ts +7 -1
- package/classes/Boot.js +36 -133
- package/classes/LoadBalancer.d.ts +8 -0
- package/classes/LoadBalancer.js +31 -0
- package/classes/MetaData.js +1 -1
- package/classes/ProxyRoute.d.ts +14 -0
- package/classes/ProxyRoute.js +40 -0
- package/classes/Settings.d.ts +4 -2
- package/classes/Settings.js +29 -10
- package/decorators/annotations.d.ts +1 -0
- package/decorators/module.js +1 -1
- package/decorators/router.d.ts +3 -2
- package/decorators/router.js +8 -23
- package/decorators/server.d.ts +16 -14
- package/decorators/server.js +46 -33
- package/engines/http/index.d.ts +17 -0
- package/engines/http/index.js +60 -0
- package/engines/teacup/index.d.ts +19 -0
- package/engines/teacup/index.js +107 -0
- package/engines/teapot/index.d.ts +23 -0
- package/engines/teapot/index.js +157 -0
- package/engines/websocket/index.d.ts +9 -0
- package/engines/websocket/index.js +37 -0
- package/helpers/boot-helper.d.ts +7 -0
- package/helpers/boot-helper.js +78 -0
- package/helpers/object-helper.d.ts +1 -0
- package/helpers/object-helper.js +9 -1
- package/helpers/server.d.ts +6 -4
- package/helpers/server.js +54 -15
- package/helpers/teapot-helper.d.ts +17 -0
- package/helpers/teapot-helper.js +47 -0
- package/helpers/websocket-helper.d.ts +5 -0
- package/helpers/websocket-helper.js +20 -0
- package/inversify.config.d.ts +9 -0
- package/inversify.config.js +8 -0
- package/libs/classNames.d.ts +1 -0
- package/libs/classNames.js +4 -0
- package/libs/constants.d.ts +4 -2
- package/libs/constants.js +8 -6
- package/libs/interfaces.d.ts +27 -15
- package/package.json +30 -8
- package/services/WebsocketService.d.ts +8 -7
- package/services/WebsocketService.js +12 -7
- package/.editorconfig +0 -31
- package/.travis.yml +0 -26
- package/CHANGELOG.md +0 -256
- package/CODE_OF_CONDUCT.md +0 -76
- package/CONTRIBUTING.md +0 -92
- package/SECURITY.md +0 -20
- package/codecov.yml +0 -10
- package/jsdocs-json.json +0 -35
- package/tools/jsdocs/helpers/table-builder.js +0 -57
- package/tools/jsdocs/plugins/custom-tags.js +0 -33
- package/tools/jsdocs/plugins/scape-at.js +0 -24
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var TeapotEngine_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
const inversify_1 = require("inversify");
|
|
7
|
+
const ProxyRoute_1 = require("../../classes/ProxyRoute");
|
|
8
|
+
const MetaData_1 = require("../../classes/MetaData");
|
|
9
|
+
const constants_1 = require("../../libs/constants");
|
|
10
|
+
const teapot_helper_1 = require("../../helpers/teapot-helper");
|
|
11
|
+
let TeapotEngine = TeapotEngine_1 = class TeapotEngine {
|
|
12
|
+
constructor(ctx, server, serverSecure, settings) {
|
|
13
|
+
this.clients = new Map();
|
|
14
|
+
this.registeredRoute = new Map();
|
|
15
|
+
this.settings = settings;
|
|
16
|
+
this.context = ctx;
|
|
17
|
+
this.server = server;
|
|
18
|
+
this.serverSecure = serverSecure;
|
|
19
|
+
this.isActive = MetaData_1.default.get(constants_1.ASSIGN_TEAPOT_KEY, this.context, 'isTeapotActive');
|
|
20
|
+
this.teapotSettings = MetaData_1.default.get(constants_1.ASSIGN_TEAPOT_KEY, this.context);
|
|
21
|
+
if (!this.isActive) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const { publicKey, privateKey } = teapot_helper_1.default.generateKeys(this.teapotSettings.serverKey);
|
|
25
|
+
this.publicKey = publicKey;
|
|
26
|
+
this.privateKey = privateKey;
|
|
27
|
+
this.serverSignature = teapot_helper_1.default.sign(this.teapotSettings.clientKey, privateKey, this.teapotSettings.serverKey);
|
|
28
|
+
this.socketServer = require('socket.io')({
|
|
29
|
+
path: '/teapot',
|
|
30
|
+
wsEngine: require('eiows').Server,
|
|
31
|
+
cookie: false
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
static header(teapotSettings) {
|
|
35
|
+
console.log(chalk.white.bold('Teapot Engine is initializing...'));
|
|
36
|
+
console.log(chalk `
|
|
37
|
+
{white.bold ;,'}
|
|
38
|
+
{green _o_} {white.bold ;:;'}
|
|
39
|
+
{blue.bold ,-.}{green '---\`}{blue.bold .__} {white.bold ; }
|
|
40
|
+
{blue.bold ((j\`=====',-'}
|
|
41
|
+
{blue.bold \`-\\ /}
|
|
42
|
+
{blue.bold \`-=-'}
|
|
43
|
+
|
|
44
|
+
{white Please assign the next} {white.bold Client Key:} {magenta.bold ${teapotSettings.clientKey}} {white to all your}
|
|
45
|
+
{yellow.bold Teacups} {white and do not share the key with anyone}
|
|
46
|
+
|
|
47
|
+
{yellow.bold NOTICE:}
|
|
48
|
+
All Communication are encrypted to ensure intruder can not connected, however, please does not share any sensitive data like keys or passwords to avoid security issues.
|
|
49
|
+
`);
|
|
50
|
+
}
|
|
51
|
+
registerTeacup(teacup) {
|
|
52
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {blue TEACUP} [{magenta.bold ${teacup.id}}]: {grey.bold Connected}`);
|
|
53
|
+
teacup.emit('handshake', {
|
|
54
|
+
key: Buffer.from(this.publicKey).toString('base64'),
|
|
55
|
+
signature: this.serverSignature.toString('base64')
|
|
56
|
+
});
|
|
57
|
+
teacup.on('handshake', this.acceptedHandshake.bind(teacup, this));
|
|
58
|
+
teacup.on('register', this.registered.bind(teacup, this));
|
|
59
|
+
teacup.on('disconnect', this.disconnected.bind(teacup, this));
|
|
60
|
+
}
|
|
61
|
+
acceptedHandshake(ctx, data) {
|
|
62
|
+
const self = this;
|
|
63
|
+
try {
|
|
64
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {blue TEACUP} [{magenta.bold ${self.id}}]: {yellow.bold Start Verification}`);
|
|
65
|
+
const clientPublicKey = Buffer.from(data.key, 'base64').toString('ascii');
|
|
66
|
+
const clientSignature = Buffer.from(data.signature, 'base64');
|
|
67
|
+
if (teapot_helper_1.default.verify(ctx.teapotSettings.clientKey, clientPublicKey, clientSignature)) {
|
|
68
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {blue TEACUP} [{magenta.bold ${self.id}}]: {green.bold Verified correctly}`);
|
|
69
|
+
ctx.clients.set(self.id, {
|
|
70
|
+
publicKey: clientPublicKey,
|
|
71
|
+
signature: clientSignature
|
|
72
|
+
});
|
|
73
|
+
self.emit('accepted', teapot_helper_1.default.encrypt({
|
|
74
|
+
signature: ctx.serverSignature.toString('base64')
|
|
75
|
+
}, clientSignature.slice(0, 32)));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {red.bold TEACUP} [{magenta.bold ${self.id}}]: Failed to verify and will be disconnected...`);
|
|
79
|
+
self.disconnect();
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {red.bold TEACUP} [{magenta.bold ${self.id}}]: Failed wiht next message: ${e.message}`);
|
|
83
|
+
self.disconnect();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
registered(ctx, data) {
|
|
87
|
+
const self = this;
|
|
88
|
+
try {
|
|
89
|
+
const message = teapot_helper_1.default.decrypt(data, ctx.serverSignature.slice(0, 32));
|
|
90
|
+
let proxyRoute;
|
|
91
|
+
if (ctx.registeredRoute.has(message.mountTo)) {
|
|
92
|
+
proxyRoute = ctx.registeredRoute.get(message.mountTo);
|
|
93
|
+
proxyRoute.registerServer(message.address, self.id);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
proxyRoute = new ProxyRoute_1.default(message.mountTo);
|
|
97
|
+
proxyRoute.registerServer(message.address, self.id);
|
|
98
|
+
ctx.registeredRoute.set(message.mountTo, proxyRoute);
|
|
99
|
+
ctx.context.getApplication().use(message.mountTo, (req, res, next) => {
|
|
100
|
+
const router = proxyRoute.registerRoute();
|
|
101
|
+
if (!proxyRoute.hasClients()) {
|
|
102
|
+
return next();
|
|
103
|
+
}
|
|
104
|
+
return router(req, res, next);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {blue TEACUP} [{magenta.bold ${self.id}}] {blue.bold <${message.address}>} <--> {white.bold ${message.mountTo}}`);
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {red.bold TEACUP} {magenta.bold ${self.id}}: Failed wiht next message: ${e.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
removeFromRoutes(routes = [], id) {
|
|
114
|
+
routes.forEach(route => {
|
|
115
|
+
const proxyRoute = this.registeredRoute.get(route);
|
|
116
|
+
proxyRoute.unregisterServer(id);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
findClientInRoutes(teacupId) {
|
|
120
|
+
const routes = [];
|
|
121
|
+
this.registeredRoute.forEach((proxyRoute, route) => {
|
|
122
|
+
if (proxyRoute.isClientOnRoute(teacupId)) {
|
|
123
|
+
routes.push(route);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return routes;
|
|
127
|
+
}
|
|
128
|
+
disconnected(ctx, reason) {
|
|
129
|
+
const self = this;
|
|
130
|
+
try {
|
|
131
|
+
const routes = ctx.findClientInRoutes(self.id);
|
|
132
|
+
ctx.removeFromRoutes(routes, self.id);
|
|
133
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {blue TEACUP} [{magenta.bold ${self.id}}]: Got disconnected by ${reason}`);
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
console.log(chalk `{cyan.bold [TEAPOT]} - {red.bold TEACUP} {magenta.bold ${self.id}}: Failed wiht next message: ${e.message}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async start() {
|
|
140
|
+
if (!this.isActive) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
TeapotEngine_1.header(this.teapotSettings);
|
|
144
|
+
this.socketServer.on('connection', this.registerTeacup.bind(this));
|
|
145
|
+
this.socketServer.listen(this.server);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
TeapotEngine = TeapotEngine_1 = tslib_1.__decorate([
|
|
149
|
+
(0, inversify_1.injectable)(),
|
|
150
|
+
tslib_1.__param(0, (0, inversify_1.inject)('context')),
|
|
151
|
+
tslib_1.__param(1, (0, inversify_1.inject)('server')),
|
|
152
|
+
tslib_1.__param(2, (0, inversify_1.inject)('secureServer')),
|
|
153
|
+
tslib_1.__param(2, (0, inversify_1.optional)()),
|
|
154
|
+
tslib_1.__param(3, (0, inversify_1.inject)('settings')),
|
|
155
|
+
tslib_1.__metadata("design:paramtypes", [Object, Object, Object, Object])
|
|
156
|
+
], TeapotEngine);
|
|
157
|
+
exports.default = TeapotEngine;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const WebsocketService_1 = require("../../services/WebsocketService");
|
|
5
|
+
const WebSocket = require("ws");
|
|
6
|
+
const inversify_1 = require("inversify");
|
|
7
|
+
let WebsocketEngine = class WebsocketEngine {
|
|
8
|
+
constructor(server, serverSecure, settings) {
|
|
9
|
+
this.canStart = false;
|
|
10
|
+
this.isDetached = false;
|
|
11
|
+
this.settings = settings;
|
|
12
|
+
this.server = server;
|
|
13
|
+
this.serverSecure = serverSecure;
|
|
14
|
+
this.canStart = this.settings.get('startWebsocket');
|
|
15
|
+
this.isDetached = this.settings.get('detachWebsocket');
|
|
16
|
+
}
|
|
17
|
+
async init() {
|
|
18
|
+
if (this.canStart) {
|
|
19
|
+
WebsocketService_1.default.init();
|
|
20
|
+
WebsocketService_1.default.getInstance().setWebSocket(new WebSocket.Server(this.isDetached ? { noServer: true } : { server: this.server }));
|
|
21
|
+
if (this.serverSecure) {
|
|
22
|
+
WebsocketService_1.default.getInstance().setSecureWebsocket(new WebSocket.Server(this.isDetached ? { noServer: true } : { server: this.serverSecure }));
|
|
23
|
+
}
|
|
24
|
+
WebsocketService_1.default.getInstance().setHttpServer(this.server);
|
|
25
|
+
WebsocketService_1.default.getInstance().setHttpServer(this.serverSecure);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
WebsocketEngine = tslib_1.__decorate([
|
|
30
|
+
(0, inversify_1.injectable)(),
|
|
31
|
+
tslib_1.__param(0, (0, inversify_1.inject)('server')),
|
|
32
|
+
tslib_1.__param(1, (0, inversify_1.inject)('secureServer')),
|
|
33
|
+
tslib_1.__param(1, (0, inversify_1.optional)()),
|
|
34
|
+
tslib_1.__param(2, (0, inversify_1.inject)('settings')),
|
|
35
|
+
tslib_1.__metadata("design:paramtypes", [Object, Object, Object])
|
|
36
|
+
], WebsocketEngine);
|
|
37
|
+
exports.default = WebsocketEngine;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BOOT_STAGES } from '../libs/constants';
|
|
2
|
+
import { Express } from 'express';
|
|
3
|
+
import Boot from '../classes/Boot';
|
|
4
|
+
export declare function resolveStage(stage: BOOT_STAGES, ctx: Boot, server: Express, ...extraArgs: unknown[]): Promise<void>;
|
|
5
|
+
export declare function resolveDirectives(instance: typeof Boot | Boot, server: Express): Promise<void>;
|
|
6
|
+
export declare function resolveStatic(instance: typeof Boot | Boot, server: Express): Promise<void>;
|
|
7
|
+
export declare function resolveProxy(ProxyContainer: any, server: Express): Promise<void>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// tslint:disable:no-duplicate-imports
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.resolveProxy = exports.resolveStatic = exports.resolveDirectives = exports.resolveStage = void 0;
|
|
5
|
+
const constants_1 = require("../libs/constants");
|
|
6
|
+
const express = require("express");
|
|
7
|
+
const MetaData_1 = require("../classes/MetaData");
|
|
8
|
+
const object_helper_1 = require("./object-helper");
|
|
9
|
+
const BootLoaderExceptions_1 = require("../exceptions/BootLoaderExceptions");
|
|
10
|
+
async function resolveStage(stage, ctx, server, ...extraArgs) {
|
|
11
|
+
try {
|
|
12
|
+
await bootloaderResolve(stage, server, ctx, ...extraArgs);
|
|
13
|
+
if (stage === constants_1.BOOT_STAGES.APPLICATION) {
|
|
14
|
+
await resolveModules(ctx, server);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
if (checkIfStageFails(e)) {
|
|
19
|
+
throw e;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.resolveStage = resolveStage;
|
|
24
|
+
async function resolveDirectives(instance, server) {
|
|
25
|
+
const registeredDirectives = MetaData_1.default.get(constants_1.REGISTERED_DIRECTIVES_KEY, (0, object_helper_1.getClass)(instance)) || [];
|
|
26
|
+
registeredDirectives.forEach((options) => {
|
|
27
|
+
server.set.call(server, options.name, ...options.settings);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
exports.resolveDirectives = resolveDirectives;
|
|
31
|
+
async function resolveStatic(instance, server) {
|
|
32
|
+
const registeredStatic = MetaData_1.default.get(constants_1.REGISTERED_STATIC_KEY, (0, object_helper_1.getClass)(instance)) || [];
|
|
33
|
+
registeredStatic.forEach((staticOptions) => {
|
|
34
|
+
if (staticOptions.virtual) {
|
|
35
|
+
server.use(staticOptions.virtual, express.static(staticOptions.root, staticOptions.options));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
server.use(express.static(staticOptions.root, staticOptions.options));
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
exports.resolveStatic = resolveStatic;
|
|
43
|
+
async function resolveProxy(ProxyContainer, server) {
|
|
44
|
+
const proxyContainer = new ProxyContainer();
|
|
45
|
+
proxyContainer.__register(server);
|
|
46
|
+
}
|
|
47
|
+
exports.resolveProxy = resolveProxy;
|
|
48
|
+
async function resolveModules(instance, server) {
|
|
49
|
+
const registeredModules = MetaData_1.default.get(constants_1.REGISTERED_MODULE_KEY, instance, 'start') || [];
|
|
50
|
+
registeredModules.forEach(Module => {
|
|
51
|
+
const moduleInstance = new Module();
|
|
52
|
+
moduleInstance.__register(server);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async function bootloaderResolve(STAGE, server, instance, ...args) {
|
|
56
|
+
const bootLoader = MetaData_1.default.get(constants_1.BOOT_STAGES_KEY, (0, object_helper_1.getClass)(instance)) || constants_1.STAGES_INIT;
|
|
57
|
+
for (const loader of bootLoader[STAGE] || []) {
|
|
58
|
+
try {
|
|
59
|
+
await selectLoaderType(loader, server, ...args);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
shouldFailIfRequire(e, loader);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function selectLoaderType(loader, server, ...args) {
|
|
67
|
+
return loader.method(server, ...args);
|
|
68
|
+
}
|
|
69
|
+
function checkIfStageFails(e) {
|
|
70
|
+
return !(e instanceof BootLoaderExceptions_1.BootLoaderSoftExceptions);
|
|
71
|
+
}
|
|
72
|
+
function shouldFailIfRequire(e, loader) {
|
|
73
|
+
const failMessage = `Failed [${loader.name}]: ${e.message}`;
|
|
74
|
+
if (!loader || loader.required) {
|
|
75
|
+
throw new BootLoaderExceptions_1.BootLoaderRequiredExceptions(failMessage);
|
|
76
|
+
}
|
|
77
|
+
throw new BootLoaderExceptions_1.BootLoaderSoftExceptions(`${failMessage} and will be not enabled`);
|
|
78
|
+
}
|
|
@@ -163,4 +163,5 @@ export declare function descriptorOf(target: any, propertyKey: string): Property
|
|
|
163
163
|
* @ignore
|
|
164
164
|
*/
|
|
165
165
|
export declare function prototypeOf(target: any): any;
|
|
166
|
+
export declare function getOwnArgumentNames(fn: Function): string[];
|
|
166
167
|
export declare function isAsyncFunction(fn: () => any): boolean;
|
package/helpers/object-helper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isAsyncFunction = exports.prototypeOf = exports.descriptorOf = exports.nameOfSymbol = exports.nameOfClass = exports.nameOf = exports.ancestorsOf = exports.getInheritedClass = exports.isPromise = exports.isEmpty = exports.isClass = exports.isObject = exports.isDate = exports.isCollection = exports.isArrayOrArrayClass = exports.isArray = exports.isBoolean = exports.isNumber = exports.isString = exports.primitiveOf = exports.isPrimitiveOrPrimitiveClass = exports.getClassOrSymbol = exports.classOf = exports.getClass = exports.getConstructor = void 0;
|
|
3
|
+
exports.isAsyncFunction = exports.getOwnArgumentNames = exports.prototypeOf = exports.descriptorOf = exports.nameOfSymbol = exports.nameOfClass = exports.nameOf = exports.ancestorsOf = exports.getInheritedClass = exports.isPromise = exports.isEmpty = exports.isClass = exports.isObject = exports.isDate = exports.isCollection = exports.isArrayOrArrayClass = exports.isArray = exports.isBoolean = exports.isNumber = exports.isString = exports.primitiveOf = exports.isPrimitiveOrPrimitiveClass = exports.getClassOrSymbol = exports.classOf = exports.getClass = exports.getConstructor = void 0;
|
|
4
4
|
/* istanbul ignore file */
|
|
5
5
|
/**
|
|
6
6
|
* Get the provide constructor.
|
|
@@ -278,6 +278,14 @@ function prototypeOf(target) {
|
|
|
278
278
|
return classOf(target) === target ? target.prototype : target;
|
|
279
279
|
}
|
|
280
280
|
exports.prototypeOf = prototypeOf;
|
|
281
|
+
const argumentsRegExp = /\(([\s\S]*?)\)/;
|
|
282
|
+
const replaceRegExp = /[ ,\n\r\t]+/;
|
|
283
|
+
// tslint:disable-next-line:ban-types
|
|
284
|
+
function getOwnArgumentNames(fn) {
|
|
285
|
+
const fnArguments = argumentsRegExp.exec(fn.toString())[1].trim();
|
|
286
|
+
return fnArguments && fnArguments.length ? fnArguments.split(replaceRegExp) : [];
|
|
287
|
+
}
|
|
288
|
+
exports.getOwnArgumentNames = getOwnArgumentNames;
|
|
281
289
|
function isAsyncFunction(fn) {
|
|
282
290
|
return fn.constructor.name === 'AsyncFunction' || fn.constructor.name.includes('__awaiter');
|
|
283
291
|
}
|
package/helpers/server.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from 'express';
|
|
2
2
|
import { ExpressiveTeaAnnotations, ExpressiveTeaArgumentOptions } from '../libs/interfaces';
|
|
3
3
|
export declare function autoResponse(request: Request, response: Response, annotations: ExpressiveTeaAnnotations[], responseResult?: any): void;
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
4
|
+
export declare function executeRequest(request: Request, response: Response, next: NextFunction): Promise<void>;
|
|
5
|
+
export declare function mapArguments(decoratedArguments: ExpressiveTeaArgumentOptions[], request: Request, response: Response, next: NextFunction, introspectedArgs?: string[]): unknown[];
|
|
6
|
+
export declare function extractParameters(target: unknown, args?: string | string[], propertyName?: string | symbol): any;
|
|
7
|
+
export declare function generateRoute(route: string, verb: string, ...settings: any): (target: object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => void;
|
|
8
|
+
export declare function router(verb: string, route: string, target: any, handler: (...args: any[]) => void | any | Promise<any>, propertyKey: string | symbol, settings?: any): void;
|
|
9
|
+
export declare function fileSettings(): any;
|
package/helpers/server.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.router = exports.generateRoute = exports.extractParameters = exports.mapArguments = exports.autoResponse = void 0;
|
|
3
|
+
exports.fileSettings = exports.router = exports.generateRoute = exports.extractParameters = exports.mapArguments = exports.executeRequest = exports.autoResponse = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const MetaData_1 = require("../classes/MetaData");
|
|
6
6
|
const constants_1 = require("../libs/constants");
|
|
7
|
+
const RequestExceptions_1 = require("../exceptions/RequestExceptions");
|
|
8
|
+
const object_helper_1 = require("./object-helper");
|
|
9
|
+
const fs = require("fs");
|
|
7
10
|
function autoResponse(request, response, annotations, responseResult) {
|
|
8
11
|
const view = (0, lodash_1.find)(annotations, { type: 'view' });
|
|
9
12
|
if (view) {
|
|
@@ -12,10 +15,31 @@ function autoResponse(request, response, annotations, responseResult) {
|
|
|
12
15
|
response.send((0, lodash_1.isNumber)(responseResult) ? responseResult.toString() : responseResult);
|
|
13
16
|
}
|
|
14
17
|
exports.autoResponse = autoResponse;
|
|
15
|
-
function
|
|
18
|
+
async function executeRequest(request, response, next) {
|
|
19
|
+
try {
|
|
20
|
+
let isNextUsed = false;
|
|
21
|
+
const nextWrapper = () => (error) => {
|
|
22
|
+
next(error);
|
|
23
|
+
isNextUsed = true;
|
|
24
|
+
};
|
|
25
|
+
const result = await this.options.handler.apply(this.self, mapArguments(this.decoratedArguments, request, response, nextWrapper(), (0, object_helper_1.getOwnArgumentNames)(this.options.handler)));
|
|
26
|
+
if (!response.headersSent && !isNextUsed) {
|
|
27
|
+
autoResponse(request, response, this.annotations, result);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
if (e instanceof RequestExceptions_1.GenericRequestException) {
|
|
32
|
+
return next(e);
|
|
33
|
+
}
|
|
34
|
+
next(new RequestExceptions_1.GenericRequestException(e.message || 'System Error'));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.executeRequest = executeRequest;
|
|
38
|
+
function mapArguments(decoratedArguments, request, response, next, introspectedArgs = []) {
|
|
16
39
|
return (0, lodash_1.chain)(decoratedArguments)
|
|
17
40
|
.sortBy('index')
|
|
18
41
|
.map((argument) => {
|
|
42
|
+
const argumentKey = (0, lodash_1.get)(introspectedArgs, argument.index);
|
|
19
43
|
switch (argument.type) {
|
|
20
44
|
case constants_1.ARGUMENT_TYPES.REQUEST:
|
|
21
45
|
return request;
|
|
@@ -24,11 +48,11 @@ function mapArguments(decoratedArguments, request, response, next) {
|
|
|
24
48
|
case constants_1.ARGUMENT_TYPES.NEXT:
|
|
25
49
|
return next;
|
|
26
50
|
case constants_1.ARGUMENT_TYPES.QUERY:
|
|
27
|
-
return extractParameters(request.query, argument.arguments);
|
|
51
|
+
return extractParameters(request.query, argument.arguments, argumentKey);
|
|
28
52
|
case constants_1.ARGUMENT_TYPES.BODY:
|
|
29
|
-
return extractParameters(request.body, argument.arguments);
|
|
53
|
+
return extractParameters(request.body, argument.arguments, argumentKey);
|
|
30
54
|
case constants_1.ARGUMENT_TYPES.GET_PARAM:
|
|
31
|
-
return extractParameters(request.params, argument.arguments);
|
|
55
|
+
return extractParameters(request.params, argument.arguments, argumentKey);
|
|
32
56
|
default:
|
|
33
57
|
return;
|
|
34
58
|
}
|
|
@@ -37,26 +61,41 @@ function mapArguments(decoratedArguments, request, response, next) {
|
|
|
37
61
|
.value();
|
|
38
62
|
}
|
|
39
63
|
exports.mapArguments = mapArguments;
|
|
40
|
-
function extractParameters(target, args) {
|
|
64
|
+
function extractParameters(target, args, propertyName) {
|
|
41
65
|
if (!args && !target) {
|
|
42
66
|
return;
|
|
43
67
|
}
|
|
44
|
-
if (
|
|
45
|
-
|
|
68
|
+
if ((0, lodash_1.size)(args)) {
|
|
69
|
+
if (Array.isArray(args)) {
|
|
70
|
+
return (0, lodash_1.pick)(target, args);
|
|
71
|
+
}
|
|
72
|
+
return (0, lodash_1.get)(target, args);
|
|
46
73
|
}
|
|
47
|
-
if (
|
|
48
|
-
return (0, lodash_1.
|
|
74
|
+
if ((0, lodash_1.has)(target, propertyName)) {
|
|
75
|
+
return (0, lodash_1.get)(target, propertyName);
|
|
49
76
|
}
|
|
50
|
-
return
|
|
77
|
+
return target;
|
|
51
78
|
}
|
|
52
79
|
exports.extractParameters = extractParameters;
|
|
53
|
-
function generateRoute(route, verb) {
|
|
54
|
-
return (target, propertyKey, descriptor) => router(verb, route, target, descriptor.value, propertyKey);
|
|
80
|
+
function generateRoute(route, verb, ...settings) {
|
|
81
|
+
return (target, propertyKey, descriptor) => router(verb, route, target, descriptor.value, propertyKey, settings);
|
|
55
82
|
}
|
|
56
83
|
exports.generateRoute = generateRoute;
|
|
57
|
-
function router(verb, route, target, handler, propertyKey) {
|
|
84
|
+
function router(verb, route, target, handler, propertyKey, settings) {
|
|
58
85
|
const existedRoutesHandlers = MetaData_1.default.get(constants_1.ROUTER_HANDLERS_KEY, target) || [];
|
|
59
|
-
existedRoutesHandlers.unshift({ verb, route, handler, target, propertyKey });
|
|
86
|
+
existedRoutesHandlers.unshift({ verb, route, handler, target, propertyKey, settings });
|
|
60
87
|
MetaData_1.default.set(constants_1.ROUTER_HANDLERS_KEY, existedRoutesHandlers, target);
|
|
61
88
|
}
|
|
62
89
|
exports.router = router;
|
|
90
|
+
function fileSettings() {
|
|
91
|
+
try {
|
|
92
|
+
if (fs.existsSync('.expressive-tea')) {
|
|
93
|
+
const configString = fs.readFileSync('.expressive-tea');
|
|
94
|
+
return JSON.parse(configString.toString());
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.fileSettings = fileSettings;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { KeyPairSyncResult } from 'crypto';
|
|
4
|
+
export interface EncryptedMessage {
|
|
5
|
+
iv: string;
|
|
6
|
+
message: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TeaGatewayMessage {
|
|
9
|
+
[property: string]: any;
|
|
10
|
+
}
|
|
11
|
+
export default class TeaGatewayHelper {
|
|
12
|
+
static encrypt(data: TeaGatewayMessage, signature: Buffer): EncryptedMessage;
|
|
13
|
+
static decrypt(data: EncryptedMessage, signature: Buffer): TeaGatewayMessage;
|
|
14
|
+
static sign(data: string, privateKey: string, passphrase: string): Buffer;
|
|
15
|
+
static verify(data: string, publicKey: string, signature: Buffer): boolean;
|
|
16
|
+
static generateKeys(passphrase: string): KeyPairSyncResult<any, any>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
class TeaGatewayHelper {
|
|
5
|
+
static encrypt(data, signature) {
|
|
6
|
+
const iv = crypto.randomBytes(16);
|
|
7
|
+
const packet = JSON.stringify(data);
|
|
8
|
+
const cipher = crypto.createCipheriv('aes-256-ctr', signature, iv);
|
|
9
|
+
const encrypted = Buffer.concat([cipher.update(packet), cipher.final()]);
|
|
10
|
+
return { iv: iv.toString('hex'), message: encrypted.toString('base64') };
|
|
11
|
+
}
|
|
12
|
+
static decrypt(data, signature) {
|
|
13
|
+
const iv = Buffer.from(data.iv, 'hex');
|
|
14
|
+
const message = Buffer.from(data.message, 'base64');
|
|
15
|
+
const decipher = crypto.createDecipheriv('aes-256-ctr', signature, iv);
|
|
16
|
+
const decrypted = Buffer.concat([decipher.update(message), decipher.final()]);
|
|
17
|
+
return JSON.parse(decrypted.toString());
|
|
18
|
+
}
|
|
19
|
+
static sign(data, privateKey, passphrase) {
|
|
20
|
+
return crypto.sign('sha256', Buffer.from(data), {
|
|
21
|
+
key: privateKey,
|
|
22
|
+
passphrase
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
static verify(data, publicKey, signature) {
|
|
26
|
+
return crypto.verify('sha256', Buffer.from(data), {
|
|
27
|
+
key: publicKey
|
|
28
|
+
}, signature);
|
|
29
|
+
}
|
|
30
|
+
static generateKeys(passphrase) {
|
|
31
|
+
const { generateKeyPairSync } = require('crypto');
|
|
32
|
+
return generateKeyPairSync('rsa', {
|
|
33
|
+
modulusLength: 2048,
|
|
34
|
+
publicKeyEncoding: {
|
|
35
|
+
type: 'spki',
|
|
36
|
+
format: 'pem'
|
|
37
|
+
},
|
|
38
|
+
privateKeyEncoding: {
|
|
39
|
+
type: 'pkcs8',
|
|
40
|
+
format: 'pem',
|
|
41
|
+
cipher: 'aes-256-cbc',
|
|
42
|
+
passphrase
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.default = TeaGatewayHelper;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initWebsocket = void 0;
|
|
4
|
+
const WebsocketService_1 = require("../services/WebsocketService");
|
|
5
|
+
const WebSocket = require("ws");
|
|
6
|
+
const Settings_1 = require("../classes/Settings");
|
|
7
|
+
async function initWebsocket(server, secureServer) {
|
|
8
|
+
const settings = Settings_1.default.getInstance();
|
|
9
|
+
const isDetached = settings.get('detachWebsocket');
|
|
10
|
+
if (settings.get('startWebsocket')) {
|
|
11
|
+
WebsocketService_1.default.init();
|
|
12
|
+
WebsocketService_1.default.getInstance().setWebSocket(new WebSocket.Server(isDetached ? { noServer: true } : { server }));
|
|
13
|
+
if (secureServer) {
|
|
14
|
+
WebsocketService_1.default.getInstance().setSecureWebsocket(new WebSocket.Server(isDetached ? { noServer: true } : { server: secureServer }));
|
|
15
|
+
}
|
|
16
|
+
WebsocketService_1.default.getInstance().setHttpServer(server);
|
|
17
|
+
WebsocketService_1.default.getInstance().setHttpServer(secureServer);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.initWebsocket = initWebsocket;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Container } from 'inversify';
|
|
2
|
+
declare const container: Container;
|
|
3
|
+
export declare const decorators: {
|
|
4
|
+
lazyInject: (serviceIdentifier: string | symbol | import("inversify/lib/interfaces/interfaces").interfaces.Newable<any> | import("inversify/lib/interfaces/interfaces").interfaces.Abstract<any>) => (proto: any, key: string) => void;
|
|
5
|
+
lazyInjectNamed: (serviceIdentifier: string | symbol | import("inversify/lib/interfaces/interfaces").interfaces.Newable<any> | import("inversify/lib/interfaces/interfaces").interfaces.Abstract<any>, named: string) => (proto: any, key: string) => void;
|
|
6
|
+
lazyInjectTagged: (serviceIdentifier: string | symbol | import("inversify/lib/interfaces/interfaces").interfaces.Newable<any> | import("inversify/lib/interfaces/interfaces").interfaces.Abstract<any>, key: string, value: any) => (proto: any, propertyName: string) => void;
|
|
7
|
+
lazyMultiInject: (serviceIdentifier: string | symbol | import("inversify/lib/interfaces/interfaces").interfaces.Newable<any> | import("inversify/lib/interfaces/interfaces").interfaces.Abstract<any>) => (proto: any, key: string) => void;
|
|
8
|
+
};
|
|
9
|
+
export default container;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decorators = void 0;
|
|
4
|
+
const inversify_1 = require("inversify");
|
|
5
|
+
const inversify_inject_decorators_1 = require("inversify-inject-decorators");
|
|
6
|
+
const container = new inversify_1.Container({ autoBindInjectable: true });
|
|
7
|
+
exports.decorators = (0, inversify_inject_decorators_1.default)(container);
|
|
8
|
+
exports.default = container;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EXPRESSIVE_TEA_PROXY_CLASS = "ExpressiveTeaProxy";
|
package/libs/constants.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export declare const EXPRESS_DIRECTIVES: string[];
|
|
|
50
50
|
export declare const BOOT_STAGES_KEY = "boot:stage-settings";
|
|
51
51
|
export declare const ROUTER_HANDLERS_KEY = "app:routes:handlers";
|
|
52
52
|
export declare const ROUTER_MIDDLEWARES_KEY = "app:routes:middlewares";
|
|
53
|
+
export declare const ROUTER_PROXIES_KEY = "app:routes:proxies";
|
|
54
|
+
export declare const PROXY_SETTING_KEY = "app:proxy:settings";
|
|
53
55
|
export declare const REGISTERED_MODEL_KEY = "app:models:registered";
|
|
54
56
|
export declare const REGISTERED_MODULE_KEY = "app:modules:registered";
|
|
55
57
|
export declare const PLUGINS_KEY = "boot:app-plugins";
|
|
@@ -57,8 +59,8 @@ export declare const REGISTERED_STATIC_KEY = "app:statics";
|
|
|
57
59
|
export declare const REGISTERED_DIRECTIVES_KEY = "app:directives";
|
|
58
60
|
export declare const ARGUMENTS_KEY = "app:routes:arguments";
|
|
59
61
|
export declare const ROUTER_ANNOTATIONS_KEY = "app:routes:annotations";
|
|
60
|
-
export declare const
|
|
61
|
-
export declare const
|
|
62
|
+
export declare const ASSIGN_TEAPOT_KEY = "app:gateway:teapot";
|
|
63
|
+
export declare const ASSIGN_TEACUP_KEY = "app:gateway:teacup";
|
|
62
64
|
export declare const ARGUMENT_TYPES: {
|
|
63
65
|
BODY: symbol;
|
|
64
66
|
GET_PARAM: symbol;
|
package/libs/constants.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* @summary Available Boot Stages
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.PROXY_PROPERTIES = exports.PROXY_METHODS = exports.ARGUMENT_TYPES = exports.
|
|
24
|
+
exports.PROXY_PROPERTIES = exports.PROXY_METHODS = exports.ARGUMENT_TYPES = exports.ASSIGN_TEACUP_KEY = exports.ASSIGN_TEAPOT_KEY = exports.ROUTER_ANNOTATIONS_KEY = exports.ARGUMENTS_KEY = exports.REGISTERED_DIRECTIVES_KEY = exports.REGISTERED_STATIC_KEY = exports.PLUGINS_KEY = exports.REGISTERED_MODULE_KEY = exports.REGISTERED_MODEL_KEY = exports.PROXY_SETTING_KEY = exports.ROUTER_PROXIES_KEY = exports.ROUTER_MIDDLEWARES_KEY = exports.ROUTER_HANDLERS_KEY = exports.BOOT_STAGES_KEY = exports.EXPRESS_DIRECTIVES = exports.STAGES_INIT = exports.BOOT_STAGES_LIST = exports.BOOT_ORDER = exports.BOOT_STAGES = void 0;
|
|
25
25
|
// tslint:enable:max-line-length
|
|
26
26
|
var BOOT_STAGES;
|
|
27
27
|
(function (BOOT_STAGES) {
|
|
@@ -46,9 +46,7 @@ var BOOT_STAGES;
|
|
|
46
46
|
exports.BOOT_ORDER = [
|
|
47
47
|
BOOT_STAGES.BOOT_DEPENDENCIES,
|
|
48
48
|
BOOT_STAGES.INITIALIZE_MIDDLEWARES,
|
|
49
|
-
|
|
50
|
-
// BOOT_STAGES.AFTER_APPLICATION_MIDDLEWARES,
|
|
51
|
-
// BOOT_STAGES.START
|
|
49
|
+
BOOT_STAGES.APPLICATION
|
|
52
50
|
];
|
|
53
51
|
exports.BOOT_STAGES_LIST = [
|
|
54
52
|
BOOT_STAGES.BOOT_DEPENDENCIES,
|
|
@@ -84,6 +82,8 @@ exports.EXPRESS_DIRECTIVES = [
|
|
|
84
82
|
exports.BOOT_STAGES_KEY = 'boot:stage-settings';
|
|
85
83
|
exports.ROUTER_HANDLERS_KEY = 'app:routes:handlers';
|
|
86
84
|
exports.ROUTER_MIDDLEWARES_KEY = 'app:routes:middlewares';
|
|
85
|
+
exports.ROUTER_PROXIES_KEY = 'app:routes:proxies';
|
|
86
|
+
exports.PROXY_SETTING_KEY = 'app:proxy:settings';
|
|
87
87
|
exports.REGISTERED_MODEL_KEY = 'app:models:registered';
|
|
88
88
|
exports.REGISTERED_MODULE_KEY = 'app:modules:registered';
|
|
89
89
|
exports.PLUGINS_KEY = 'boot:app-plugins';
|
|
@@ -91,8 +91,8 @@ exports.REGISTERED_STATIC_KEY = 'app:statics';
|
|
|
91
91
|
exports.REGISTERED_DIRECTIVES_KEY = 'app:directives';
|
|
92
92
|
exports.ARGUMENTS_KEY = 'app:routes:arguments';
|
|
93
93
|
exports.ROUTER_ANNOTATIONS_KEY = 'app:routes:annotations';
|
|
94
|
-
exports.
|
|
95
|
-
exports.
|
|
94
|
+
exports.ASSIGN_TEAPOT_KEY = 'app:gateway:teapot';
|
|
95
|
+
exports.ASSIGN_TEACUP_KEY = 'app:gateway:teacup';
|
|
96
96
|
exports.ARGUMENT_TYPES = {
|
|
97
97
|
BODY: Symbol('BODY'),
|
|
98
98
|
GET_PARAM: Symbol('GET_PARAM'),
|
|
@@ -113,6 +113,8 @@ var PROXY_METHODS;
|
|
|
113
113
|
PROXY_METHODS["PROXY_REQ_OPT_DECORATOR"] = "proxyReqOptDecorator";
|
|
114
114
|
PROXY_METHODS["PROXY_REQ_BODY_DECORATOR"] = "proxyReqBodyDecorator";
|
|
115
115
|
})(PROXY_METHODS = exports.PROXY_METHODS || (exports.PROXY_METHODS = {}));
|
|
116
|
+
// 'limit' | 'memoizeHost' | 'https' | 'preserveHostHdr' | 'parseReqBody' |
|
|
117
|
+
// 'reqAsBuffer' | 'reqBodyEncoding' | 'timeout';
|
|
116
118
|
var PROXY_PROPERTIES;
|
|
117
119
|
(function (PROXY_PROPERTIES) {
|
|
118
120
|
PROXY_PROPERTIES["LIMIT"] = "limit";
|