@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
package/.circleci/config.yml
CHANGED
|
@@ -23,9 +23,18 @@ jobs:
|
|
|
23
23
|
- checkout
|
|
24
24
|
# Next, the node orb's install-packages step will install the dependencies from a package.json.
|
|
25
25
|
# The orb install-packages step will also automatically cache them for faster future runs.
|
|
26
|
+
- restore_cache:
|
|
27
|
+
keys:
|
|
28
|
+
- expressive-tea-{{ checksum "package.json" }}
|
|
29
|
+
- expressive-tea-
|
|
30
|
+
|
|
26
31
|
- node/install-packages:
|
|
27
32
|
# If you are using yarn, change the line below from "npm" to "yarn"
|
|
28
33
|
pkg-manager: yarn
|
|
34
|
+
- save_cache:
|
|
35
|
+
paths:
|
|
36
|
+
- node_modules
|
|
37
|
+
key: expressive-tea-{{ checksum "package.json" }}
|
|
29
38
|
- run:
|
|
30
39
|
name: Expressive Tea Tests
|
|
31
40
|
command: npm test
|
package/README.md
CHANGED
|
@@ -1,77 +1,76 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<!-- Npm Version -->
|
|
3
3
|
<a href="https://www.npmjs.com/package/@zerooneit/expressive-tea">
|
|
4
|
-
<img alt="npm (scoped)" src="https://img.shields.io/npm/v/@zerooneit/expressive-tea?style=
|
|
5
|
-
</a>
|
|
6
|
-
|
|
7
|
-
<!-- Test Coverage -->
|
|
8
|
-
<a href="https://codecov.io/gh/Expressive-Tea/expresive-tea">
|
|
9
|
-
<img alt="Codecov" src="https://img.shields.io/codecov/c/github/Expressive-Tea/expresive-tea?style=for-the-badge">
|
|
10
|
-
</a>
|
|
11
|
-
|
|
12
|
-
<!-- Build -->
|
|
13
|
-
<a href="https://travis-ci.org/Zero-OneiT/expresive-tea">
|
|
14
|
-
<img alt="Circle CI" src="https://img.shields.io/circleci/build/github/Expressive-Tea/expresive-tea/master?style=for-the-badge">
|
|
15
|
-
</a>
|
|
16
|
-
|
|
17
|
-
<!-- License -->
|
|
18
|
-
<a href="https://github.com/Zero-OneiT/expresive-tea/blob/develop/LICENSE">
|
|
19
|
-
<img alt="NPM" src="https://img.shields.io/npm/l/@zerooneit/expressive-tea?style=for-the-badge">
|
|
4
|
+
<img alt="npm (scoped)" src="https://img.shields.io/npm/v/@zerooneit/expressive-tea?style=flat-square">
|
|
20
5
|
</a>
|
|
21
6
|
|
|
22
7
|
<!-- Downloads -->
|
|
23
8
|
<a href="https://www.npmjs.com/package/@zerooneit/expressive-tea">
|
|
24
|
-
<img alt="npm" src="https://img.shields.io/npm/dw/@zerooneit/expressive-tea?style=
|
|
9
|
+
<img alt="npm" src="https://img.shields.io/npm/dw/@zerooneit/expressive-tea?style=flat-square">
|
|
25
10
|
</a>
|
|
26
11
|
|
|
27
|
-
<!-- Dependencies
|
|
12
|
+
<!-- Dependencies
|
|
28
13
|
<a href="https://libraries.io/npm/@zerooneit%2Fexpressive-tea">
|
|
29
|
-
<img alt="Libraries.io dependency status for latest release, scoped npm package" src="https://img.shields.io/librariesio/release/npm/@zerooneit/expressive-tea?style=
|
|
14
|
+
<img alt="Libraries.io dependency status for latest release, scoped npm package" src="https://img.shields.io/librariesio/release/npm/@zerooneit/expressive-tea?style=flat-square">
|
|
15
|
+
</a>
|
|
16
|
+
-->
|
|
17
|
+
|
|
18
|
+
<!-- License
|
|
19
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea/blob/develop/LICENSE">
|
|
20
|
+
<img alt="NPM" src="https://img.shields.io/npm/l/@zerooneit/expressive-tea?style=flat-square">
|
|
30
21
|
</a>
|
|
22
|
+
-->
|
|
31
23
|
|
|
32
24
|
<!-- Vulnerabilities -->
|
|
33
25
|
<a href="https://snyk.io//test/github/Expressive-Tea/expresive-tea?targetFile=package.json">
|
|
34
|
-
<img alt="Snyk Vulnerabilities for npm package" src="https://img.shields.io/snyk/vulnerabilities/github/
|
|
26
|
+
<img alt="Snyk Vulnerabilities for npm package" src="https://img.shields.io/snyk/vulnerabilities/github/expressive-tea/expresive-tea?style=flat-square">
|
|
35
27
|
</a>
|
|
36
28
|
|
|
37
29
|
<!-- Last Commit
|
|
38
|
-
<a href="https://github.com/
|
|
39
|
-
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/
|
|
40
|
-
</a>
|
|
41
|
-
|
|
30
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea">
|
|
31
|
+
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/Expressive-Tea/expresive-tea?style=flat-square">
|
|
32
|
+
</a>
|
|
33
|
+
-->
|
|
42
34
|
<!-- Stars -->
|
|
43
|
-
<a href="https://github.com/
|
|
44
|
-
<img alt="GitHub stars" src="https://img.shields.io/github/stars/
|
|
35
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea/stargazers">
|
|
36
|
+
<img alt="GitHub stars" src="https://img.shields.io/github/stars/Expressive-Tea/expresive-tea?style=flat-square">
|
|
45
37
|
</a>
|
|
46
38
|
|
|
47
|
-
<!-- Source Rank
|
|
39
|
+
<!-- Source Rank
|
|
48
40
|
<a href="https://libraries.io/npm/@zerooneit%2Fexpressive-tea/sourcerank">
|
|
49
|
-
<img alt="Libraries.io SourceRank, scoped npm package" src="https://img.shields.io/librariesio/sourcerank/npm/@zerooneit/expressive-tea?style=
|
|
50
|
-
</a>
|
|
51
|
-
|
|
41
|
+
<img alt="Libraries.io SourceRank, scoped npm package" src="https://img.shields.io/librariesio/sourcerank/npm/@zerooneit/expressive-tea?style=flat-square">
|
|
42
|
+
</a>
|
|
43
|
+
-->
|
|
52
44
|
<!-- Rating
|
|
53
45
|
<a href="https://pkgreview.dev/npm/@zerooneit%2Fexpressive-tea">
|
|
54
|
-
<img alt="pkgreview.dev Package Ratings" src="https://img.shields.io/pkgreview/rating/npm/@zerooneit/expressive-tea?style=
|
|
55
|
-
</a>
|
|
56
|
-
|
|
46
|
+
<img alt="pkgreview.dev Package Ratings" src="https://img.shields.io/pkgreview/rating/npm/@zerooneit/expressive-tea?style=flat-square">
|
|
47
|
+
</a>
|
|
48
|
+
-->
|
|
57
49
|
<!-- Issues
|
|
58
|
-
<a href="https://github.com/
|
|
59
|
-
<img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/Zero-Oneit/expresive-tea?style=
|
|
60
|
-
</a>
|
|
61
|
-
|
|
62
|
-
<!-- Gitter
|
|
63
|
-
<a href="https://gitter.im/
|
|
64
|
-
<img alt="Gitter" src="https://img.shields.io/gitter/room/zero-oneit/expresive-tea?style=
|
|
50
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea/issues">
|
|
51
|
+
<img alt="GitHub issues" src="https://img.shields.io/github/issues-raw/Zero-Oneit/expresive-tea?style=flat-square">
|
|
52
|
+
</a>
|
|
53
|
+
-->
|
|
54
|
+
<!-- Gitter
|
|
55
|
+
<a href="https://gitter.im/Expressive-Tea/expresive-tea">
|
|
56
|
+
<img alt="Gitter" src="https://img.shields.io/gitter/room/zero-oneit/expresive-tea?style=flat-square">
|
|
57
|
+
</a>
|
|
58
|
+
-->
|
|
59
|
+
<!-- Test Coverage -->
|
|
60
|
+
<a href="https://codecov.io/gh/Expressive-Tea/expresive-tea">
|
|
61
|
+
<img alt="Codecov" src="https://img.shields.io/codecov/c/github/expressive-tea/expresive-tea?label=Test%20coverage&style=flat-square">
|
|
65
62
|
</a>
|
|
66
63
|
|
|
67
|
-
|
|
64
|
+
<!-- Build -->
|
|
65
|
+
<a href="https://travis-ci.org/Expressive-Tea/expresive-tea">
|
|
66
|
+
<img alt="Travis (.org) branch" src="https://ci.zero-oneit.systems/buildStatus/icon?job=Expressive+Tea&style=flat-square">
|
|
67
|
+
</a>
|
|
68
68
|
</p>
|
|
69
69
|
|
|
70
|
-
|
|
71
70
|
<!-- PROJECT LOGO -->
|
|
72
71
|
<br />
|
|
73
72
|
<p align="center">
|
|
74
|
-
<a href="https://github.com/
|
|
73
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea">
|
|
75
74
|
<img src="images/logo.png" alt="Logo" width="160" />
|
|
76
75
|
</a>
|
|
77
76
|
|
|
@@ -85,9 +84,9 @@
|
|
|
85
84
|
<br />
|
|
86
85
|
<a href="https://codesandbox.io/s/expressive-tea-2kmg7?fontsize=14&hidenavigation=1&theme=dark">View Demo</a>
|
|
87
86
|
·
|
|
88
|
-
<a href="https://github.com/
|
|
87
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea/issues">Report Bug</a>
|
|
89
88
|
·
|
|
90
|
-
<a href="https://github.com/
|
|
89
|
+
<a href="https://github.com/Expressive-Tea/expresive-tea/issues">Request Feature</a>
|
|
91
90
|
</p>
|
|
92
91
|
</p>
|
|
93
92
|
|
|
@@ -110,28 +109,31 @@
|
|
|
110
109
|
* [Principal Sponsors](#principal-sponsors)
|
|
111
110
|
* [Stay on touch](#stay-on-touch)
|
|
112
111
|
* [License](#license)
|
|
113
|
-
* [
|
|
112
|
+
* [Disclamers](#disclaimers)
|
|
114
113
|
|
|
115
114
|
|
|
116
115
|
## About the project
|
|
117
|
-
Expressive Tea is
|
|
118
|
-
[Typescript](https://www.typescriptlang.org/). As Expressive Tea is using [express](https://expressjs.com/) is compatible with all the middlewares and modules and
|
|
119
|
-
easy migration from express applications.
|
|
116
|
+
Expressive Tea is framework to help build server-side applications in [NodeJS](https://nodejs.org/) and use modern Javascript powered by
|
|
117
|
+
[Typescript](https://www.typescriptlang.org/). As Expressive Tea is using [express](https://expressjs.com/) is compatible with all the middlewares and modules and provide
|
|
118
|
+
an easy migration from express applications.
|
|
120
119
|
|
|
121
|
-
Expressive Tea is a flexible framework
|
|
120
|
+
Expressive Tea is a flexible framework but also giving freedom to the developer to build their own architectures
|
|
121
|
+
by providing descriptive decorators, a plugin engine, shareable modules and moder Javascript.
|
|
122
122
|
|
|
123
123
|
### Motivation
|
|
124
|
-
Server-side applications
|
|
125
|
-
|
|
124
|
+
Server-side applications it contains awesome tools, helpers, and libraries to improve productivity but at same time it
|
|
125
|
+
haves a large downside, **architecture**. Expressive Tea main motivation is relief the stress of the architecture by
|
|
126
|
+
providing a shareable/pluggable projects, you can write a plugin to setting up express middlewares, databases settings,
|
|
127
|
+
or websockets to name some; and you can share them through your next projects or the community.
|
|
126
128
|
|
|
127
129
|
Main goal is making uncomplicaded creation of server-side applications, modulables, plugables, free and efortless
|
|
128
130
|
architecture.
|
|
129
131
|
|
|
130
132
|
### Features
|
|
131
|
-
* Easy Setting up and start
|
|
133
|
+
* Easy Setting up and start up of webserver.
|
|
132
134
|
* Extends and configuration with plugins and well-defined boot stages.
|
|
133
|
-
* Modules are not
|
|
134
|
-
* Declare Server Middlewares configuration as hard or soft
|
|
135
|
+
* Modules are not hard dependencies and can be shareable between projects.
|
|
136
|
+
* Declare Server Middlewares configuration as hard or soft dependency at server level.
|
|
135
137
|
* Dependency Injection is available for controllers as providers declared in modules using InversifyJs.
|
|
136
138
|
* Declarative Router on Controllers.
|
|
137
139
|
* Declarative Verbs and Middlewares under module and verb level.
|
|
@@ -143,6 +145,7 @@ architecture.
|
|
|
143
145
|
* [Typescript](https://www.typescriptlang.org/) - Main Language
|
|
144
146
|
* [Inversify](https://github.com/inversify/InversifyJS/) - Used for dependency Injection
|
|
145
147
|
* [Reflect Metadata](https://github.com/rbuckton/reflect-metadata) - Used to get code metadata.
|
|
148
|
+
* [YARN](https://yarnpkg.com/) - Used to build and dependencies.
|
|
146
149
|
|
|
147
150
|
## Getting Started
|
|
148
151
|
|
|
@@ -151,30 +154,10 @@ architecture.
|
|
|
151
154
|
**Important!** Expressive Tea requires Node >= 6, Express >= 4, TypeScript >= 2.0 and the `experimentalDecorators`,
|
|
152
155
|
`lib` compilation options in your `tsconfig.json` with the next configuration.
|
|
153
156
|
|
|
154
|
-
Expressive Tea is
|
|
155
|
-
|
|
156
|
-
### Installation using Tea CLI
|
|
157
|
-
|
|
158
|
-
#### Installing tea
|
|
159
|
-
```bash
|
|
160
|
-
npm i -g @expressive-tea/tea
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
#### Create a Project
|
|
164
|
-
```bash
|
|
165
|
-
tea brew <name_of_project>
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
#### Run Project
|
|
169
|
-
|
|
170
|
-
In the project directory.
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
tea serve
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Installation by pure typescript
|
|
157
|
+
Expressive Tea is not having any configuration of any Express Plugin or any database connection beside is built it
|
|
158
|
+
on Express it is woking as **Bring Your Own Architecture**.
|
|
177
159
|
|
|
160
|
+
### Installation
|
|
178
161
|
```bash
|
|
179
162
|
npm i --save @zerooneit/expressive-tea
|
|
180
163
|
```
|
|
@@ -198,7 +181,7 @@ npm i --save @zerooneit/expressive-tea
|
|
|
198
181
|
}
|
|
199
182
|
```
|
|
200
183
|
### Examples
|
|
201
|
-
You can
|
|
184
|
+
You can looking into our simple example [here](https://github.com/Expressive-Tea/expressive-tea-sandbox), or edit or see how is working on our live preview using th button below.
|
|
202
185
|
|
|
203
186
|
<p align="center">
|
|
204
187
|
<br/>
|
|
@@ -209,26 +192,25 @@ You can look into our simple example [here](https://github.com/Zero-OneiT/expres
|
|
|
209
192
|
|
|
210
193
|
## Contributing
|
|
211
194
|
|
|
212
|
-
Please read [CONTRIBUTING.md](
|
|
195
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
|
|
213
196
|
|
|
214
197
|
## Versioning
|
|
215
198
|
|
|
216
|
-
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/
|
|
199
|
+
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/Expressive-Tea/expresive-tea/tags).
|
|
217
200
|
|
|
218
201
|
## Contributors
|
|
219
202
|
|
|
220
203
|
* **Diego Resendez** - *Lead Developer / Author* - [zerooneit](https://github.com/zerooneit)
|
|
221
204
|
|
|
222
|
-
See also the list of [contributors](https://github.com/
|
|
205
|
+
See also the list of [contributors](https://github.com/Expressive-Tea/expresive-tea/contributors) who participated in this project.
|
|
223
206
|
|
|
224
207
|
## Support
|
|
225
|
-
If you are
|
|
226
|
-
|
|
227
|
-
If you want to share your thoughts with the development team or join us, you will do so using the [official mailing list](https://groups.google.com/forum/#!forum/expressive-tea/). You can check out the
|
|
228
|
-
[wiki](https://github.com/Zero-OneiT/expresive-tea/blob/develop/README.md) to learn more about Expressive Tea internals or check our [documentation](https://zero-oneit.github.io/expresive-tea/).
|
|
208
|
+
If you are experience any kind of issues we will be happy to help. You can report an issue using the [issues page](https://github.com/Expressive-Tea/expresive-tea/issues) or the [chat](https://gitter.im/Expressive-Tea/expresive-tea). You can also ask questions at [Stack overflow](http://stackoverflow.com/tags/expressive-tea) using the `expressive-tea` tag.
|
|
229
209
|
|
|
230
|
-
|
|
210
|
+
If you want to share your thoughts with the development team or join us you will be able to do so using the [official the mailing list](https://groups.google.com/forum/#!forum/expressive-tea/). You can check out the
|
|
211
|
+
[wiki](https://github.com/Expressive-Tea/expresive-tea/blob/develop/README.md) to learn more about Expressive Tea internals or check our [documentation](https://docs.expressive-tea.io).
|
|
231
212
|
|
|
213
|
+
Expressive Tea is an open source project, our goal is create an awesome framework that helps to build marvelous server side applications. If you like to join as Sponsor or backer to continue grow, please you can contact us on [projects@zero-oneit.com](mailto:projects@zero-oneit.com)
|
|
232
214
|
#### Principal Sponsors
|
|
233
215
|
|
|
234
216
|
<table style="text-align:center;"><tr><td>
|
|
@@ -243,7 +225,7 @@ Expressive Tea is an open-source project; our goal is to create a fantastic fram
|
|
|
243
225
|
* Email - [support@expressive-tea.io](support@expressive-tea.io)
|
|
244
226
|
|
|
245
227
|
## License
|
|
246
|
-
This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details
|
|
228
|
+
This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details
|
|
247
229
|
|
|
248
230
|
<p align="center">
|
|
249
231
|
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2FZero-OneiT%2Fexpresive-tea?ref=badge_large">
|
package/classes/Boot.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import '../inversify.config';
|
|
1
3
|
import { Express } from 'express';
|
|
2
4
|
import Settings from '../classes/Settings';
|
|
3
5
|
import { ExpressiveTeaApplication } from '../libs/interfaces';
|
|
@@ -36,6 +38,11 @@ declare abstract class Boot {
|
|
|
36
38
|
*/
|
|
37
39
|
private readonly server;
|
|
38
40
|
constructor();
|
|
41
|
+
/**
|
|
42
|
+
* Get Express Application
|
|
43
|
+
* @returns Express
|
|
44
|
+
*/
|
|
45
|
+
getApplication(): Express;
|
|
39
46
|
/**
|
|
40
47
|
* Bootstrap and verify that all the required plugins are correctly configured and proceed to attach all the
|
|
41
48
|
* registered modules. <b>Remember</b> this is the unique method that must be decorated for the Register Module
|
|
@@ -45,5 +52,4 @@ declare abstract class Boot {
|
|
|
45
52
|
*/
|
|
46
53
|
start(): Promise<ExpressiveTeaApplication>;
|
|
47
54
|
}
|
|
48
|
-
export declare function resolveProxy(ProxyContainer: any, server: Express): Promise<void>;
|
|
49
55
|
export default Boot;
|
package/classes/Boot.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
require("reflect-metadata");
|
|
4
|
+
require("../inversify.config");
|
|
4
5
|
const $P = require("bluebird");
|
|
5
6
|
// tslint:disable-next-line:no-duplicate-imports
|
|
6
7
|
const express = require("express");
|
|
7
8
|
const fs = require("fs");
|
|
8
9
|
const http = require("http");
|
|
9
10
|
const https = require("https");
|
|
10
|
-
const MetaData_1 = require("../classes/MetaData");
|
|
11
11
|
const Settings_1 = require("../classes/Settings");
|
|
12
|
-
const BootLoaderExceptions_1 = require("../exceptions/BootLoaderExceptions");
|
|
13
|
-
const object_helper_1 = require("../helpers/object-helper");
|
|
14
12
|
const constants_1 = require("../libs/constants");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
13
|
+
const index_1 = require("../engines/http/index");
|
|
14
|
+
const index_2 = require("../engines/websocket/index");
|
|
15
|
+
const index_3 = require("../engines/teapot/index");
|
|
16
|
+
const teacup_1 = require("../engines/teacup");
|
|
17
|
+
// tslint:disable-next-line:no-duplicate-imports
|
|
18
|
+
const inversify_config_1 = require("../inversify.config");
|
|
17
19
|
/**
|
|
18
20
|
* Expressive Tea Application interface is the response from an started application, contains the express application
|
|
19
21
|
* and a node http server instance.
|
|
@@ -32,15 +34,6 @@ const WebsocketService_1 = require("../services/WebsocketService");
|
|
|
32
34
|
*/
|
|
33
35
|
class Boot {
|
|
34
36
|
constructor() {
|
|
35
|
-
/**
|
|
36
|
-
* Maintain a reference to Singleton instance of Settings, if settings still does not initialized it will created
|
|
37
|
-
* automatically when extended class create a new instance.
|
|
38
|
-
*
|
|
39
|
-
* @type {Settings}
|
|
40
|
-
* @public
|
|
41
|
-
* @summary Server Settings instance reference
|
|
42
|
-
*/
|
|
43
|
-
this.settings = new Settings_1.default();
|
|
44
37
|
/**
|
|
45
38
|
* Automatically create an Express application instance which will be user to configure over all the boot stages.
|
|
46
39
|
* @type {Express}
|
|
@@ -49,7 +42,14 @@ class Boot {
|
|
|
49
42
|
* @summary Express Application instance internal property.
|
|
50
43
|
*/
|
|
51
44
|
this.server = express();
|
|
52
|
-
this.settings.
|
|
45
|
+
this.settings = Settings_1.default.getInstance(this);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get Express Application
|
|
49
|
+
* @returns Express
|
|
50
|
+
*/
|
|
51
|
+
getApplication() {
|
|
52
|
+
return this.server;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Bootstrap and verify that all the required plugins are correctly configured and proceed to attach all the
|
|
@@ -61,53 +61,33 @@ class Boot {
|
|
|
61
61
|
async start() {
|
|
62
62
|
return new $P(async (resolver, rejector) => {
|
|
63
63
|
try {
|
|
64
|
+
const localContainer = inversify_config_1.default.createChild();
|
|
64
65
|
const privateKey = this.settings.get('privateKey');
|
|
65
66
|
const certificate = this.settings.get('certificate');
|
|
66
|
-
const startWebsocket = this.settings.get('startWebsocket');
|
|
67
|
-
const detachWebsocket = this.settings.get('detachWebsocket');
|
|
68
|
-
const serverConfigQueue = [];
|
|
69
|
-
// tslint:disable-next-line:one-variable-per-declaration
|
|
70
|
-
let ws, wss;
|
|
71
67
|
const server = http.createServer(this.server);
|
|
72
68
|
const secureServer = privateKey && certificate && https.createServer({
|
|
73
69
|
cert: fs.readFileSync(certificate).toString('utf-8'),
|
|
74
70
|
key: fs.readFileSync(privateKey).toString('utf-8')
|
|
75
71
|
}, this.server);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
await
|
|
86
|
-
await
|
|
87
|
-
await
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
await
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
})));
|
|
96
|
-
if (secureServer) {
|
|
97
|
-
serverConfigQueue.push(new $P(resolve => secureServer.listen(this.settings.get('securePort'), () => {
|
|
98
|
-
console.log(`Running Secure HTTP Server on [${this.settings.get('securePort')}]`);
|
|
99
|
-
resolve();
|
|
100
|
-
})));
|
|
101
|
-
}
|
|
102
|
-
await $P.all([
|
|
103
|
-
resolveStage(constants_1.BOOT_STAGES.AFTER_APPLICATION_MIDDLEWARES, this, this.server),
|
|
104
|
-
resolveStage(constants_1.BOOT_STAGES.ON_HTTP_CREATION, this, this.server, server, secureServer)
|
|
105
|
-
]);
|
|
106
|
-
$P.all(serverConfigQueue)
|
|
107
|
-
.then(() => {
|
|
108
|
-
return resolveStage(constants_1.BOOT_STAGES.START, this, this.server, server, secureServer);
|
|
109
|
-
})
|
|
110
|
-
.then(() => resolver({ application: this.server, server, secureServer }));
|
|
72
|
+
// Injectables
|
|
73
|
+
localContainer.bind('server').toConstantValue(server);
|
|
74
|
+
localContainer.bind('secureServer').toConstantValue(secureServer || undefined);
|
|
75
|
+
localContainer.bind('context').toConstantValue(this);
|
|
76
|
+
localContainer.bind('settings').toConstantValue(this.settings);
|
|
77
|
+
const httpEngine = localContainer.resolve(index_1.default);
|
|
78
|
+
const websocketEngine = localContainer.resolve(index_2.default);
|
|
79
|
+
const teapotEngine = localContainer.resolve(index_3.default);
|
|
80
|
+
const teacupEngine = localContainer.resolve(teacup_1.default);
|
|
81
|
+
await websocketEngine.init();
|
|
82
|
+
await httpEngine.init();
|
|
83
|
+
await httpEngine.resolveProxyContainers();
|
|
84
|
+
await httpEngine.resolveStages(constants_1.BOOT_ORDER);
|
|
85
|
+
await httpEngine.resolveStages([constants_1.BOOT_STAGES.AFTER_APPLICATION_MIDDLEWARES, constants_1.BOOT_STAGES.ON_HTTP_CREATION], server, secureServer);
|
|
86
|
+
const listenerServers = await httpEngine.start();
|
|
87
|
+
await httpEngine.resolveStages([constants_1.BOOT_STAGES.START], ...listenerServers);
|
|
88
|
+
await teapotEngine.start();
|
|
89
|
+
await teacupEngine.start();
|
|
90
|
+
resolver({ application: this.server, server, secureServer });
|
|
111
91
|
}
|
|
112
92
|
catch (e) {
|
|
113
93
|
return rejector(e);
|
|
@@ -115,81 +95,4 @@ class Boot {
|
|
|
115
95
|
});
|
|
116
96
|
}
|
|
117
97
|
}
|
|
118
|
-
async function resolveStage(stage, ctx, server, ...extraArgs) {
|
|
119
|
-
try {
|
|
120
|
-
await bootloaderResolve(stage, server, ctx, ...extraArgs);
|
|
121
|
-
if (stage === constants_1.BOOT_STAGES.APPLICATION) {
|
|
122
|
-
await resolveModules(ctx, server);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
catch (e) {
|
|
126
|
-
checkIfStageFails(e);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
async function resolveDirectives(instance, server) {
|
|
130
|
-
const registeredDirectives = MetaData_1.default.get(constants_1.REGISTERED_DIRECTIVES_KEY, (0, object_helper_1.getClass)(instance)) || [];
|
|
131
|
-
registeredDirectives.forEach((options) => {
|
|
132
|
-
server.set.call(server, options.name, ...options.settings);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
async function resolveStatic(instance, server) {
|
|
136
|
-
const registeredStatic = MetaData_1.default.get(constants_1.REGISTERED_STATIC_KEY, (0, object_helper_1.getClass)(instance)) || [];
|
|
137
|
-
registeredStatic.forEach((staticOptions) => {
|
|
138
|
-
if (staticOptions.virtual) {
|
|
139
|
-
server.use(staticOptions.virtual, express.static(staticOptions.root, staticOptions.options));
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
server.use(express.static(staticOptions.root, staticOptions.options));
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
async function resolveModules(instance, server) {
|
|
147
|
-
const registeredModules = MetaData_1.default.get(constants_1.REGISTERED_MODULE_KEY, instance, 'start') || [];
|
|
148
|
-
registeredModules.forEach(Module => {
|
|
149
|
-
const moduleInstance = new Module();
|
|
150
|
-
moduleInstance.__register(server);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
async function bootloaderResolve(STAGE, server, instance, ...args) {
|
|
154
|
-
const bootLoader = MetaData_1.default.get(constants_1.BOOT_STAGES_KEY, (0, object_helper_1.getClass)(instance)) || constants_1.STAGES_INIT;
|
|
155
|
-
for (const loader of bootLoader[STAGE] || []) {
|
|
156
|
-
try {
|
|
157
|
-
await selectLoaderType(loader, server, ...args);
|
|
158
|
-
}
|
|
159
|
-
catch (e) {
|
|
160
|
-
shouldFailIfRequire(e, loader);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
async function resolveProxyContainers(context) {
|
|
165
|
-
const ProxyContainers = MetaData_1.default.get(constants_1.ROUTER_PROXIES_KEY, (0, object_helper_1.getClass)(context)) || [];
|
|
166
|
-
for (const Container of ProxyContainers) {
|
|
167
|
-
resolveProxy(Container, context.server);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
async function resolveProxy(ProxyContainer, server) {
|
|
171
|
-
const proxyContainer = new ProxyContainer();
|
|
172
|
-
proxyContainer.__register(server);
|
|
173
|
-
}
|
|
174
|
-
exports.resolveProxy = resolveProxy;
|
|
175
|
-
async function selectLoaderType(loader, server, ...args) {
|
|
176
|
-
return loader.method(server, ...args);
|
|
177
|
-
}
|
|
178
|
-
function checkIfStageFails(e) {
|
|
179
|
-
if (e instanceof BootLoaderExceptions_1.BootLoaderSoftExceptions) {
|
|
180
|
-
console.info(e.message);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
console.error(e.message);
|
|
184
|
-
// Re Throwing Error to Get it a top level.
|
|
185
|
-
throw e;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
function shouldFailIfRequire(e, loader) {
|
|
189
|
-
const failMessage = `Failed [${loader.name}]: ${e.message}`;
|
|
190
|
-
if (!loader || loader.required) {
|
|
191
|
-
throw new BootLoaderExceptions_1.BootLoaderRequiredExceptions(failMessage);
|
|
192
|
-
}
|
|
193
|
-
throw new BootLoaderExceptions_1.BootLoaderSoftExceptions(`${failMessage} and will be not enabled`);
|
|
194
|
-
}
|
|
195
98
|
exports.default = Boot;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class LoadBalancer {
|
|
4
|
+
/**
|
|
5
|
+
* @offset should be used for unit testing and nothing else.
|
|
6
|
+
*/
|
|
7
|
+
constructor(count, offset = 0) {
|
|
8
|
+
this.bins = new Array(count);
|
|
9
|
+
// Initializes the elements of the array to zero.
|
|
10
|
+
for (let i = 0; i < this.bins.length; i++) {
|
|
11
|
+
this.bins[i] = offset;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
pick() {
|
|
15
|
+
const a = Math.trunc(Math.random() * this.bins.length);
|
|
16
|
+
const b = Math.trunc(Math.random() * this.bins.length);
|
|
17
|
+
const result = this.bins[a] < this.bins[b] ? a : b;
|
|
18
|
+
// Accounts for overflow if enough requests go through this balancer.
|
|
19
|
+
if (this.bins[result] === Number.MAX_SAFE_INTEGER) {
|
|
20
|
+
// Resets all bins as it assumes they have all received an equal
|
|
21
|
+
// number of requests. Starts again from a blank state.
|
|
22
|
+
for (let i = 0; i < this.bins.length; i++) {
|
|
23
|
+
this.bins[i] = 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Increments the number of requests assigned to this bin.
|
|
27
|
+
this.bins[result]++;
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = LoadBalancer;
|
package/classes/MetaData.js
CHANGED
|
@@ -32,8 +32,8 @@ class Metadata {
|
|
|
32
32
|
return Reflect.hasMetadata(key, (0, object_helper_1.getClass)(target), propertyKey);
|
|
33
33
|
}
|
|
34
34
|
catch (er) {
|
|
35
|
+
return false;
|
|
35
36
|
}
|
|
36
|
-
return false;
|
|
37
37
|
}
|
|
38
38
|
static hasOwn(key, target, propertyKey) {
|
|
39
39
|
return Reflect.hasOwnMetadata(key, (0, object_helper_1.getClass)(target), propertyKey);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RequestHandler } from 'express';
|
|
2
|
+
export default class ProxyRoute {
|
|
3
|
+
readonly registeredOn: string;
|
|
4
|
+
private balancer;
|
|
5
|
+
private servers;
|
|
6
|
+
private clients;
|
|
7
|
+
private lastServerSelected;
|
|
8
|
+
constructor(registeredOn: string);
|
|
9
|
+
hasClients(): boolean;
|
|
10
|
+
isClientOnRoute(teacupId: string): boolean;
|
|
11
|
+
registerServer(address: string, teacupId: string): void;
|
|
12
|
+
unregisterServer(teacupId: string): void;
|
|
13
|
+
registerRoute(): RequestHandler;
|
|
14
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const proxy = require("express-http-proxy");
|
|
4
|
+
const LoadBalancer_1 = require("./LoadBalancer");
|
|
5
|
+
const lodash_1 = require("lodash");
|
|
6
|
+
class ProxyRoute {
|
|
7
|
+
constructor(registeredOn) {
|
|
8
|
+
this.servers = [];
|
|
9
|
+
this.clients = [];
|
|
10
|
+
this.lastServerSelected = 0;
|
|
11
|
+
this.registeredOn = registeredOn;
|
|
12
|
+
}
|
|
13
|
+
hasClients() {
|
|
14
|
+
return (0, lodash_1.size)(this.clients) > 0;
|
|
15
|
+
}
|
|
16
|
+
isClientOnRoute(teacupId) {
|
|
17
|
+
return (0, lodash_1.includes)(this.clients, teacupId);
|
|
18
|
+
}
|
|
19
|
+
registerServer(address, teacupId) {
|
|
20
|
+
this.servers.push({ teacupId, address });
|
|
21
|
+
this.clients.push(teacupId);
|
|
22
|
+
this.balancer = new LoadBalancer_1.default(this.servers.length, this.lastServerSelected);
|
|
23
|
+
}
|
|
24
|
+
unregisterServer(teacupId) {
|
|
25
|
+
const index = (0, lodash_1.indexOf)(this.clients, teacupId);
|
|
26
|
+
this.servers.splice(index, 1);
|
|
27
|
+
this.clients.splice(index, 1);
|
|
28
|
+
this.balancer = new LoadBalancer_1.default(this.servers.length);
|
|
29
|
+
}
|
|
30
|
+
registerRoute() {
|
|
31
|
+
return proxy(() => {
|
|
32
|
+
this.lastServerSelected = this.balancer.pick();
|
|
33
|
+
const server = this.servers[this.lastServerSelected];
|
|
34
|
+
return server.address;
|
|
35
|
+
}, {
|
|
36
|
+
memoizeHost: false
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.default = ProxyRoute;
|