@toa.io/bindings.http 0.1.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2020-present Artem Gurtovoi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@toa.io/bindings.http",
3
+ "version": "0.1.0-dev.0",
4
+ "description": "Toa HTTP Binding",
5
+ "author": "temich <tema.gurtovoy@gmail.com>",
6
+ "homepage": "https://github.com/toa-io/toa#readme",
7
+ "main": "src/index.js",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/toa-io/toa.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/toa-io/toa/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "scripts": {
19
+ "test": "echo \"Error: run tests from root\" && exit 1"
20
+ },
21
+ "peerDependencies": {
22
+ "@toa.io/core": "^0.0.0",
23
+ "@toa.io/gears": "^0.0.0"
24
+ },
25
+ "dependencies": {
26
+ "agentkeepalive": "4.1.4",
27
+ "express": "4.17.1",
28
+ "node-fetch": "2.6.6"
29
+ },
30
+ "devDependencies": {
31
+ "@babel/parser": "^7.16.2"
32
+ },
33
+ "gitHead": "632df6cead03909ad2cfb8852e178914ac4ab5d2"
34
+ }
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const fetch = require('node-fetch')
4
+ const { Connector } = require('@toa.io/core')
5
+
6
+ const resource = require('./resource')
7
+
8
+ class Consumer extends Connector {
9
+ #agent
10
+ #locator
11
+ #endpoint
12
+ #url
13
+
14
+ constructor (agent, locator, endpoint) {
15
+ super()
16
+
17
+ this.#agent = agent
18
+ this.#locator = locator
19
+ this.#endpoint = endpoint
20
+ }
21
+
22
+ async connection () {
23
+ this.#url = Consumer.#locate(this.#locator, this.#endpoint)
24
+ }
25
+
26
+ async request (request) {
27
+ const method = resource.method
28
+
29
+ const reply = await fetch(this.#url, {
30
+ method,
31
+ body: JSON.stringify(request),
32
+ headers: { 'Content-Type': 'application/json' },
33
+ agent: this.#agent
34
+ })
35
+
36
+ return reply.json()
37
+ }
38
+
39
+ static #locate (locator, endpoint) {
40
+ const host = process.env.TOA_ENV === 'dev' ? 'localhost' : locator.host()
41
+ const path = resource.path(locator, endpoint)
42
+
43
+ return 'http://' + host + ':' + PORT + path
44
+ }
45
+ }
46
+
47
+ const PORT = 3000
48
+
49
+ exports.Consumer = Consumer
package/src/factory.js ADDED
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ const Agent = require('agentkeepalive')
4
+
5
+ const { Consumer } = require('./consumer')
6
+ const { Producer } = require('./producer')
7
+ const { Server } = require('./server')
8
+
9
+ class Factory {
10
+ #server
11
+ #agents = {}
12
+
13
+ constructor () {
14
+ this.#server = new Server()
15
+ }
16
+
17
+ producer (locator, endpoints, target) {
18
+ return new Producer(this.#server, locator, endpoints, target)
19
+ }
20
+
21
+ consumer (locator, endpoint) {
22
+ const id = locator.id
23
+
24
+ if (!this.#agents[id]) this.#agents[id] = new Agent(AGENT_OPTIONS)
25
+
26
+ return new Consumer(this.#agents[id], locator, endpoint)
27
+ }
28
+ }
29
+
30
+ const AGENT_OPTIONS = { keepAlive: process.env.TOA_ENV !== 'dev' && process.env.TOA_ENV !== 'test' }
31
+
32
+ exports.Factory = Factory
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ 'use strict'
2
+
3
+ const { Factory } = require('./factory')
4
+
5
+ exports.Factory = Factory
6
+ exports.properties = { async: false }
@@ -0,0 +1,39 @@
1
+ 'use strict'
2
+
3
+ const { Connector } = require('@toa.io/core')
4
+
5
+ const resource = require('./resource')
6
+
7
+ class Producer extends Connector {
8
+ #server
9
+ #locator
10
+ #endpoints
11
+ #producer
12
+
13
+ constructor (server, locator, endpoints, producer) {
14
+ super()
15
+
16
+ this.#server = server
17
+ this.#locator = locator
18
+ this.#endpoints = endpoints
19
+ this.#producer = producer
20
+
21
+ this.#bind()
22
+
23
+ this.depends(server)
24
+ this.depends(producer)
25
+ }
26
+
27
+ #bind () {
28
+ this.#endpoints.map((endpoint) => this.#endpoint(endpoint))
29
+ }
30
+
31
+ #endpoint (endpoint) {
32
+ const method = resource.method
33
+ const path = resource.path(this.#locator, endpoint)
34
+
35
+ this.#server.reply(method, path, async (request) => this.#producer.invoke(endpoint, request))
36
+ }
37
+ }
38
+
39
+ exports.Producer = Producer
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const path = (locator, endpoint) => ['', locator.domain, locator.name, endpoint].join('/')
4
+ const method = 'POST'
5
+
6
+ exports.path = path
7
+ exports.method = method
package/src/server.js ADDED
@@ -0,0 +1,61 @@
1
+ 'use strict'
2
+
3
+ const express = require('express')
4
+
5
+ const { Connector } = require('@toa.io/core')
6
+ const { console } = require('@toa.io/gears')
7
+
8
+ class Server extends Connector {
9
+ #app
10
+ #server
11
+
12
+ #port
13
+
14
+ constructor () {
15
+ super()
16
+
17
+ this.#app = express()
18
+ this.#app.disable('x-powered-by')
19
+ this.#app.use(express.json())
20
+
21
+ this.#port = PORT
22
+ }
23
+
24
+ reply (verb, route, invocation) {
25
+ this.#app[verb.toLowerCase()](route, async (req, res) => {
26
+ const reply = await invocation(req.body)
27
+
28
+ res.json(reply)
29
+ })
30
+ }
31
+
32
+ async connection () {
33
+ return new Promise((resolve, reject) => {
34
+ this.#server = this.#app.listen(this.#port, () => {
35
+ console.info(`HTTP server started at :${this.#port}`)
36
+
37
+ this.#server.off('error', reject)
38
+ resolve()
39
+ })
40
+
41
+ this.#server.on('error', reject)
42
+ })
43
+ }
44
+
45
+ async disconnection () {
46
+ return new Promise((resolve, reject) => {
47
+ this.#server.close(() => {
48
+ console.info(`HTTP server at :${this.#port} stopped`)
49
+
50
+ this.#server.off('error', reject)
51
+ resolve()
52
+ })
53
+
54
+ this.#server.on('error', reject)
55
+ })
56
+ }
57
+ }
58
+
59
+ const PORT = 3000
60
+
61
+ exports.Server = Server