@superhero/core 1.8.5 → 4.0.0-beta.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/README.md +108 -739
- package/index.js +654 -54
- package/index.test.js +94 -0
- package/package.json +17 -31
- package/worker.js +12 -0
- package/LICENCE +0 -20
- package/bootstrap/config.js +0 -7
- package/bootstrap/index.js +0 -19
- package/bootstrap/locator.js +0 -16
- package/cli/config.js +0 -7
- package/cli/index.js +0 -49
- package/cli/locator.js +0 -17
- package/composer/bootstrap/error/schema-not-resolvable.js +0 -10
- package/composer/bootstrap/index.js +0 -62
- package/composer/bootstrap/locator.js +0 -20
- package/composer/config.js +0 -49
- package/composer/error/filter-is-not-honering-contract.js +0 -13
- package/composer/error/invalid-attribute.js +0 -13
- package/composer/error/invalid-collection.js +0 -13
- package/composer/error/invalid-schema.js +0 -13
- package/composer/error/schema-not-found.js +0 -13
- package/composer/error/validator-is-not-honering-contract.js +0 -13
- package/composer/error/validator-not-found.js +0 -13
- package/composer/filter/boolean/index.js +0 -44
- package/composer/filter/boolean/locator.js +0 -11
- package/composer/filter/decimal/index.js +0 -38
- package/composer/filter/decimal/locator.js +0 -11
- package/composer/filter/index.js +0 -10
- package/composer/filter/integer/index.js +0 -38
- package/composer/filter/integer/locator.js +0 -11
- package/composer/filter/json/index.js +0 -23
- package/composer/filter/json/locator.js +0 -11
- package/composer/filter/schema/error/missing-schema-definition.js +0 -13
- package/composer/filter/schema/index.js +0 -49
- package/composer/filter/schema/locator.js +0 -17
- package/composer/filter/string/index.js +0 -50
- package/composer/filter/string/locator.js +0 -11
- package/composer/filter/timestamp/index.js +0 -45
- package/composer/filter/timestamp/locator.js +0 -11
- package/composer/index.js +0 -180
- package/composer/locator.js +0 -17
- package/composer/validator/boolean/error/invalid.js +0 -13
- package/composer/validator/boolean/index.js +0 -17
- package/composer/validator/boolean/locator.js +0 -11
- package/composer/validator/decimal/error/invalid.js +0 -13
- package/composer/validator/decimal/index.js +0 -59
- package/composer/validator/decimal/locator.js +0 -11
- package/composer/validator/index.js +0 -10
- package/composer/validator/integer/error/invalid.js +0 -13
- package/composer/validator/integer/index.js +0 -65
- package/composer/validator/integer/locator.js +0 -11
- package/composer/validator/json/error/invalid.js +0 -13
- package/composer/validator/json/index.js +0 -23
- package/composer/validator/json/locator.js +0 -11
- package/composer/validator/schema/error/invalid.js +0 -13
- package/composer/validator/schema/index.js +0 -13
- package/composer/validator/schema/locator.js +0 -11
- package/composer/validator/string/error/invalid.js +0 -13
- package/composer/validator/string/index.js +0 -59
- package/composer/validator/string/locator.js +0 -11
- package/composer/validator/timestamp/error/invalid.js +0 -13
- package/composer/validator/timestamp/index.js +0 -54
- package/composer/validator/timestamp/locator.js +0 -11
- package/configuration/config.js +0 -7
- package/configuration/index.js +0 -23
- package/configuration/locator.js +0 -22
- package/console/config.js +0 -15
- package/console/index.js +0 -23
- package/console/locator.js +0 -21
- package/console/observer/error/config.js +0 -7
- package/console/observer/error/index.js +0 -14
- package/console/observer/error/locator.js +0 -17
- package/console/observer/info/config.js +0 -7
- package/console/observer/info/index.js +0 -14
- package/console/observer/info/locator.js +0 -17
- package/console/observer/warning/config.js +0 -7
- package/console/observer/warning/index.js +0 -14
- package/console/observer/warning/locator.js +0 -17
- package/core/config.js +0 -21
- package/core/error.js +0 -10
- package/deepcopy/config.js +0 -7
- package/deepcopy/error/failed-to-fast-copy.js +0 -10
- package/deepcopy/index.js +0 -18
- package/deepcopy/locator.js +0 -11
- package/deepfind/config.js +0 -7
- package/deepfind/index.js +0 -11
- package/deepfind/locator.js +0 -11
- package/deepfreeze/config.js +0 -7
- package/deepfreeze/index.js +0 -20
- package/deepfreeze/locator.js +0 -11
- package/deepmerge/config.js +0 -7
- package/deepmerge/index.js +0 -42
- package/deepmerge/locator.js +0 -11
- package/eventbus/bootstrap/error/observer-contract-not-honered.js +0 -10
- package/eventbus/bootstrap/index.js +0 -33
- package/eventbus/bootstrap/locator.js +0 -20
- package/eventbus/config.js +0 -17
- package/eventbus/index.js +0 -21
- package/eventbus/locator.js +0 -25
- package/eventbus/observer.js +0 -9
- package/factory.js +0 -55
- package/http/request/config.js +0 -7
- package/http/request/locator.js +0 -21
- package/http/server/config.js +0 -23
- package/http/server/dispatcher/chain/error/dispatcher-chain-ended.js +0 -10
- package/http/server/dispatcher/chain/index.js +0 -41
- package/http/server/dispatcher/chain/locator.js +0 -20
- package/http/server/dispatcher/collection/builder/error/dispatcher-can-not-be-resolved.js +0 -10
- package/http/server/dispatcher/collection/builder/error/not-honering-dispatcher-contract.js +0 -10
- package/http/server/dispatcher/collection/builder/index.js +0 -56
- package/http/server/dispatcher/collection/builder/locator.js +0 -20
- package/http/server/dispatcher/error/bad-gateway.js +0 -12
- package/http/server/dispatcher/error/bad-request.js +0 -12
- package/http/server/dispatcher/error/conflict.js +0 -12
- package/http/server/dispatcher/error/forbidden.js +0 -12
- package/http/server/dispatcher/error/gateway-timeout.js +0 -12
- package/http/server/dispatcher/error/index.js +0 -10
- package/http/server/dispatcher/error/method-not-allowed.js +0 -12
- package/http/server/dispatcher/error/not-implemented.js +0 -12
- package/http/server/dispatcher/error/page-not-found.js +0 -12
- package/http/server/dispatcher/error/request-timeout.js +0 -12
- package/http/server/dispatcher/error/server-error.js +0 -12
- package/http/server/dispatcher/error/service-unavailable.js +0 -12
- package/http/server/dispatcher/error/unauthorized.js +0 -12
- package/http/server/dispatcher/index.js +0 -26
- package/http/server/dispatcher/rest.js +0 -75
- package/http/server/error/no-endpoint-defined-in-route.js +0 -10
- package/http/server/error/view-contract-not-honered.js +0 -10
- package/http/server/index.js +0 -195
- package/http/server/locator.js +0 -34
- package/http/server/request/builder/index.js +0 -53
- package/http/server/request/builder/locator.js +0 -20
- package/http/server/route/builder/error/dto-invalid-reference.js +0 -10
- package/http/server/route/builder/error/routes-invalid-type.js +0 -10
- package/http/server/route/builder/index.js +0 -88
- package/http/server/route/builder/locator.js +0 -20
- package/http/server/session/builder/index.js +0 -34
- package/http/server/session/builder/locator.js +0 -11
- package/http/server/view/index.js +0 -12
- package/http/server/view/json/index.js +0 -17
- package/http/server/view/json/locator.js +0 -11
- package/http/server/view/locator.js +0 -11
- package/http/server/view/stream/index.js +0 -10
- package/http/server/view/stream/locator.js +0 -11
- package/http/server/view/text/index.js +0 -15
- package/http/server/view/text/locator.js +0 -11
- package/locator/constituent.js +0 -26
- package/locator/error/locator-not-implemented.js +0 -10
- package/locator/error/service-undefined.js +0 -10
- package/locator/index.js +0 -29
- package/path/config.js +0 -7
- package/path/index.js +0 -63
- package/path/locator.js +0 -11
- package/process/bootstrap/index.js +0 -31
- package/process/bootstrap/locator.js +0 -17
- package/process/config.js +0 -12
- package/process/index.js +0 -9
- package/process/locator.js +0 -11
- package/test/api/config.js +0 -43
- package/test/api/endpoint/append-calculation.js +0 -41
- package/test/api/endpoint/create-calculation.js +0 -18
- package/test/api/middleware/authentication.js +0 -27
- package/test/calculator/calculation.js +0 -29
- package/test/calculator/config.js +0 -14
- package/test/calculator/error/calculation-could-not-be-found.js +0 -13
- package/test/calculator/error/invalid-calculation-type.js +0 -13
- package/test/calculator/index.js +0 -67
- package/test/calculator/locator.js +0 -20
- package/test/init.js +0 -2
- package/test/logger/config.js +0 -15
- package/test/logger/index.js +0 -17
- package/test/logger/locator.js +0 -20
- package/test/mocha.opts +0 -4
- package/test/test.calculation.js +0 -58
- package/test/test.logger.js +0 -35
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const NotImplementedError = require('./error/not-implemented')
|
|
2
|
-
|
|
3
|
-
class HttpDispatcher
|
|
4
|
-
{
|
|
5
|
-
constructor(route, request, session, locator, view)
|
|
6
|
-
{
|
|
7
|
-
this.route = route
|
|
8
|
-
this.request = request
|
|
9
|
-
this.session = session
|
|
10
|
-
this.locator = locator
|
|
11
|
-
this.view = view
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
dispatch()
|
|
15
|
-
{
|
|
16
|
-
const msg = '"dispatch" method is not implemented'
|
|
17
|
-
throw new NotImplementedError(msg)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
onError(error)
|
|
21
|
-
{
|
|
22
|
-
throw error
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = HttpDispatcher
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
const
|
|
2
|
-
HttpDispatcher = require('.'),
|
|
3
|
-
BadRequestError = require('./error/bad-request'),
|
|
4
|
-
MethodNotAllowedError = require('./error/method-not-allowed'),
|
|
5
|
-
NotImplementedError = require('./error/not-implemented'),
|
|
6
|
-
ServerError = require('./error/server-error')
|
|
7
|
-
|
|
8
|
-
class HttpDispatcherRest extends HttpDispatcher
|
|
9
|
-
{
|
|
10
|
-
async dispatch()
|
|
11
|
-
{
|
|
12
|
-
const allowed = this.fetchAllowedMethods(this.route)
|
|
13
|
-
|
|
14
|
-
if(!allowed.includes(this.request.method))
|
|
15
|
-
{
|
|
16
|
-
this.view.headers['Allowed'] = allowed.join(',')
|
|
17
|
-
throw new MethodNotAllowedError(`Method not allowed: "${this.request.method}"`)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
switch(this.request.method)
|
|
21
|
-
{
|
|
22
|
-
case 'OPTIONS':
|
|
23
|
-
{
|
|
24
|
-
this.view.headers['Allowed'] = allowed.join(',')
|
|
25
|
-
break
|
|
26
|
-
}
|
|
27
|
-
case 'GET' :
|
|
28
|
-
case 'POST' :
|
|
29
|
-
case 'PUT' :
|
|
30
|
-
case 'DELETE' :
|
|
31
|
-
{
|
|
32
|
-
const action = this.request.method.toLowerCase()
|
|
33
|
-
await this[action]()
|
|
34
|
-
break
|
|
35
|
-
}
|
|
36
|
-
default :
|
|
37
|
-
{
|
|
38
|
-
const msg = `Unrecognized method "${method}", expected one of: "${allowed.join(',')}"`
|
|
39
|
-
throw new BadRequestError(msg)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
fetchAllowedMethods(route)
|
|
45
|
-
{
|
|
46
|
-
if(!route.allowed)
|
|
47
|
-
{
|
|
48
|
-
throw new ServerError('No allowed methods are defined in the route')
|
|
49
|
-
}
|
|
50
|
-
if(!Array.isArray(route.allowed))
|
|
51
|
-
{
|
|
52
|
-
throw new ServerError('Allowed methods in route is not defined as an array')
|
|
53
|
-
}
|
|
54
|
-
if(!route.allowed.every((allowed) => typeof allowed === 'string'))
|
|
55
|
-
{
|
|
56
|
-
throw new ServerError('Allowed http method must be a set of strings')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const allowed = route.allowed.map((method) => method.toUpperCase())
|
|
60
|
-
|
|
61
|
-
if(!allowed.includes('OPTIONS'))
|
|
62
|
-
{
|
|
63
|
-
allowed.push('OPTIONS')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return allowed
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get() { throw new NotImplementedError }
|
|
70
|
-
post() { throw new NotImplementedError }
|
|
71
|
-
put() { throw new NotImplementedError }
|
|
72
|
-
delete() { throw new NotImplementedError }
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = HttpDispatcherRest
|
package/http/server/index.js
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
const
|
|
2
|
-
NoEndpointDefinedInRouteError = require('./error/no-endpoint-defined-in-route'),
|
|
3
|
-
ViewContractNotHoneredError = require('./error/view-contract-not-honered')
|
|
4
|
-
|
|
5
|
-
class HttpServer
|
|
6
|
-
{
|
|
7
|
-
/**
|
|
8
|
-
* @param {http.Server} server
|
|
9
|
-
*/
|
|
10
|
-
constructor(server, requestBuilder, sessionBuilder, routeBuilder,
|
|
11
|
-
dispatcherCollectionBuilder, dispatcherChain, configuration,
|
|
12
|
-
locator, eventbus, domainFactory)
|
|
13
|
-
{
|
|
14
|
-
this.server = server
|
|
15
|
-
this.requestBuilder = requestBuilder
|
|
16
|
-
this.sessionBuilder = sessionBuilder
|
|
17
|
-
this.routeBuilder = routeBuilder
|
|
18
|
-
this.dispatcherCollectionBuilder = dispatcherCollectionBuilder
|
|
19
|
-
this.dispatcherChain = dispatcherChain
|
|
20
|
-
this.configuration = configuration
|
|
21
|
-
this.locator = locator
|
|
22
|
-
this.eventbus = eventbus
|
|
23
|
-
this.domainFactory = domainFactory
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
listen(...args)
|
|
27
|
-
{
|
|
28
|
-
this.server.listen(...args)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
onListening(done)
|
|
32
|
-
{
|
|
33
|
-
return this.server.listening
|
|
34
|
-
? done()
|
|
35
|
-
: this.server.once('listening', done)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
close()
|
|
39
|
-
{
|
|
40
|
-
return new Promise((accept, reject) =>
|
|
41
|
-
this.server.close((error) =>
|
|
42
|
-
error
|
|
43
|
-
? reject(error)
|
|
44
|
-
: accept()))
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
onRequest(input, output)
|
|
48
|
-
{
|
|
49
|
-
const domain = this.domainFactory.create()
|
|
50
|
-
|
|
51
|
-
domain.add(input)
|
|
52
|
-
domain.add(output)
|
|
53
|
-
|
|
54
|
-
domain.on('error', this.onError.bind(this, input, output, domain))
|
|
55
|
-
input.on('aborted', this.onAborted.bind(this, output))
|
|
56
|
-
output.on('timeout', this.onTimeout.bind(this, output))
|
|
57
|
-
output.on('finish', this.onFinish .bind(this, input, output, domain))
|
|
58
|
-
|
|
59
|
-
domain.run(() => this.dispatch(input, output, domain))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
onAborted(output)
|
|
63
|
-
{
|
|
64
|
-
output.end()
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
onFinish(input, output, domain)
|
|
68
|
-
{
|
|
69
|
-
let
|
|
70
|
-
emitters = 0,
|
|
71
|
-
timeouts = 0
|
|
72
|
-
|
|
73
|
-
for(const member of domain.members)
|
|
74
|
-
'removeAllListeners' in member
|
|
75
|
-
? emitters++
|
|
76
|
-
: timeouts++
|
|
77
|
-
|
|
78
|
-
if(domain.members.length > 2)
|
|
79
|
-
{
|
|
80
|
-
const msg =
|
|
81
|
-
[
|
|
82
|
-
`Finished session did not clear all domain members!`,
|
|
83
|
-
`Expected: 2 (response and request)`,
|
|
84
|
-
`Recieved: ${domain.members.length}`,
|
|
85
|
-
`Emitters: ${emitters}`,
|
|
86
|
-
`Timeouts: ${timeouts}`
|
|
87
|
-
].join('\n')
|
|
88
|
-
|
|
89
|
-
this.eventbus.emit('core.warning', msg)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
domain.exit()
|
|
93
|
-
domain.removeAllListeners()
|
|
94
|
-
input .removeAllListeners()
|
|
95
|
-
output.removeAllListeners()
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
onTimeout(output)
|
|
99
|
-
{
|
|
100
|
-
output.writeHead(408)
|
|
101
|
-
output.end('Request Timeout')
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
onError(input, output, domain, error)
|
|
105
|
-
{
|
|
106
|
-
switch(error.code)
|
|
107
|
-
{
|
|
108
|
-
case 'E_HTTP_DISPATCHER':
|
|
109
|
-
{
|
|
110
|
-
output.writeHead(error.status)
|
|
111
|
-
output.end(error.message)
|
|
112
|
-
break
|
|
113
|
-
}
|
|
114
|
-
case 'E_NO_ENDPOINT_DEFINED_IN_ROUTE':
|
|
115
|
-
{
|
|
116
|
-
this.eventbus.emit('core.error', error)
|
|
117
|
-
|
|
118
|
-
output.writeHead(404)
|
|
119
|
-
output.end('Endpoint Not Found')
|
|
120
|
-
break
|
|
121
|
-
}
|
|
122
|
-
default:
|
|
123
|
-
{
|
|
124
|
-
this.eventbus.emit('core.error', error)
|
|
125
|
-
|
|
126
|
-
output.writeHead(500)
|
|
127
|
-
output.end('Internal Server Error')
|
|
128
|
-
break
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async dispatch(input, output, domain)
|
|
134
|
-
{
|
|
135
|
-
const
|
|
136
|
-
routes = this.configuration.find('http.server.routes'),
|
|
137
|
-
session = await this.sessionBuilder.build(input, output, domain),
|
|
138
|
-
request = await this.requestBuilder.build(input),
|
|
139
|
-
route = await this.routeBuilder.build(routes, request),
|
|
140
|
-
viewModel = this.createViewModel()
|
|
141
|
-
|
|
142
|
-
if(!route.endpoint)
|
|
143
|
-
{
|
|
144
|
-
const msg = `No endpoint defined in route for the request: ${request.method} -> ${request.url}`
|
|
145
|
-
throw new NoEndpointDefinedInRouteError(msg)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const dispatchers = await this.dispatcherCollectionBuilder.build(route, request, session, viewModel)
|
|
149
|
-
await this.dispatcherChain.dispatch(dispatchers)
|
|
150
|
-
|
|
151
|
-
if(!output.finished)
|
|
152
|
-
{
|
|
153
|
-
output.writeProcessing()
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
viewType = viewModel.meta.view || route.view || 'http/server/view',
|
|
157
|
-
view = this.locator.locate(viewType)
|
|
158
|
-
|
|
159
|
-
if(typeof view.write !== 'function')
|
|
160
|
-
{
|
|
161
|
-
const msg = `The service "${viewType}" does not honer the view contract`
|
|
162
|
-
throw new ViewContractNotHoneredError(msg)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
await view.write(output, viewModel, route)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Allowing the body to be set, in order to be able to have arrays and strings as a response body
|
|
171
|
-
* @returns {Object} frozen
|
|
172
|
-
*/
|
|
173
|
-
createViewModel()
|
|
174
|
-
{
|
|
175
|
-
let body = {}
|
|
176
|
-
|
|
177
|
-
const viewModel =
|
|
178
|
-
{
|
|
179
|
-
get body()
|
|
180
|
-
{
|
|
181
|
-
return body
|
|
182
|
-
},
|
|
183
|
-
set body(_body)
|
|
184
|
-
{
|
|
185
|
-
body = _body
|
|
186
|
-
},
|
|
187
|
-
headers : {},
|
|
188
|
-
meta : {}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return Object.freeze(viewModel)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
module.exports = HttpServer
|
package/http/server/locator.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const HttpServer = require('.')
|
|
2
|
-
|
|
3
|
-
class HttpServerLocator
|
|
4
|
-
{
|
|
5
|
-
constructor(locator)
|
|
6
|
-
{
|
|
7
|
-
this.locator = locator
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
locate()
|
|
11
|
-
{
|
|
12
|
-
const
|
|
13
|
-
configuration = this.locator.locate('configuration'),
|
|
14
|
-
serverOptions = configuration.find('http.server.options'),
|
|
15
|
-
server = require('http').createServer(serverOptions),
|
|
16
|
-
requestBuilder = this.locator.locate('http/server/request/builder'),
|
|
17
|
-
sessionFactory = this.locator.locate('http/server/session/builder'),
|
|
18
|
-
routeBuilder = this.locator.locate('http/server/route/builder'),
|
|
19
|
-
dispatcherCollectionBuilder = this.locator.locate('http/server/dispatcher/collection/builder'),
|
|
20
|
-
dispatcherChain = this.locator.locate('http/server/dispatcher/chain'),
|
|
21
|
-
eventbus = this.locator.locate('eventbus'),
|
|
22
|
-
domainFactory = require('domain'),
|
|
23
|
-
httpServer = new HttpServer(server, requestBuilder, sessionFactory, routeBuilder,
|
|
24
|
-
dispatcherCollectionBuilder, dispatcherChain, configuration,
|
|
25
|
-
this.locator, eventbus, domainFactory)
|
|
26
|
-
|
|
27
|
-
server.timeout = configuration.find('http.server.timeout')
|
|
28
|
-
server.on('request', httpServer.onRequest.bind(httpServer))
|
|
29
|
-
|
|
30
|
-
return httpServer
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = HttpServerLocator
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
const
|
|
2
|
-
url = require('url'),
|
|
3
|
-
querystring = require('querystring')
|
|
4
|
-
|
|
5
|
-
class HttpRequestBuilder
|
|
6
|
-
{
|
|
7
|
-
constructor(deepfreeze)
|
|
8
|
-
{
|
|
9
|
-
this.deepfreeze = deepfreeze
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async build(input)
|
|
13
|
-
{
|
|
14
|
-
const
|
|
15
|
-
parsedUrl = url.parse(input.url, true),
|
|
16
|
-
request =
|
|
17
|
-
{
|
|
18
|
-
headers : input.headers,
|
|
19
|
-
method : input.method.toUpperCase(),
|
|
20
|
-
url : parsedUrl.pathname.replace(/\/+$/g, ''),
|
|
21
|
-
query : parsedUrl.query,
|
|
22
|
-
body : await this.fetchBody(input)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return this.deepfreeze.freeze(request)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async fetchBody(input)
|
|
29
|
-
{
|
|
30
|
-
return new Promise((accept, reject) =>
|
|
31
|
-
{
|
|
32
|
-
let body = ''
|
|
33
|
-
|
|
34
|
-
input.on('error', reject)
|
|
35
|
-
input.on('data', (data) => body += data)
|
|
36
|
-
input.on('end', () => this.parseBody(input.headers['content-type'], body).then(accept).catch(reject))
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async parseBody(contentType, body)
|
|
41
|
-
{
|
|
42
|
-
switch(contentType)
|
|
43
|
-
{
|
|
44
|
-
case 'application/json':
|
|
45
|
-
return JSON.parse(body || '{}')
|
|
46
|
-
|
|
47
|
-
default:
|
|
48
|
-
return querystring.parse(body)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
module.exports = HttpRequestBuilder
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const HttpRequestBuilder = require('.')
|
|
2
|
-
|
|
3
|
-
class HttpRequestBuilderLocator
|
|
4
|
-
{
|
|
5
|
-
constructor(locator)
|
|
6
|
-
{
|
|
7
|
-
this.locator = locator
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
locate()
|
|
11
|
-
{
|
|
12
|
-
const
|
|
13
|
-
deepfreeze = this.locator.locate('deepfreeze'),
|
|
14
|
-
httpRequestBuilder = new HttpRequestBuilder(deepfreeze)
|
|
15
|
-
|
|
16
|
-
return httpRequestBuilder
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = HttpRequestBuilderLocator
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
const
|
|
2
|
-
RoutesInvalidTypeError = require('./error/routes-invalid-type'),
|
|
3
|
-
DtoInvalidReferenceError = require('./error/dto-invalid-reference')
|
|
4
|
-
|
|
5
|
-
class HttpRouteBuilder
|
|
6
|
-
{
|
|
7
|
-
constructor(deepmerge)
|
|
8
|
-
{
|
|
9
|
-
this.deepmerge = deepmerge
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
build(routes, request)
|
|
13
|
-
{
|
|
14
|
-
if(typeof routes !== 'object')
|
|
15
|
-
{
|
|
16
|
-
throw new RoutesInvalidTypeError(`routes must be built from an object`)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
validRoutes = this.fetchValidRoutes(routes, request),
|
|
21
|
-
route = this.deepmerge.merge({}, ...validRoutes)
|
|
22
|
-
|
|
23
|
-
route.dto = this.composeDto(request, route.dto)
|
|
24
|
-
|
|
25
|
-
return route
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
fetchValidRoutes(routes, request)
|
|
29
|
-
{
|
|
30
|
-
const validRoutes = []
|
|
31
|
-
for(const name in routes)
|
|
32
|
-
{
|
|
33
|
-
const
|
|
34
|
-
route = routes[name],
|
|
35
|
-
url = route.url && new RegExp(`^${route.url.replace(/\/+$/g, '')}$`),
|
|
36
|
-
method = route.method && new RegExp(`^${route.method}$`, 'i')
|
|
37
|
-
|
|
38
|
-
if(request.url .match(url)
|
|
39
|
-
&& request.method .match(method))
|
|
40
|
-
{
|
|
41
|
-
validRoutes.push(route)
|
|
42
|
-
|
|
43
|
-
// once we found an endpoint, the route is completed
|
|
44
|
-
if(route.endpoint)
|
|
45
|
-
{
|
|
46
|
-
break
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return validRoutes
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
composeDto(request, map)
|
|
54
|
-
{
|
|
55
|
-
const dto = {}
|
|
56
|
-
for(const key in map)
|
|
57
|
-
for(const type in map[key])
|
|
58
|
-
switch(type)
|
|
59
|
-
{
|
|
60
|
-
case 'body':
|
|
61
|
-
{
|
|
62
|
-
const body_key = map[key][type]
|
|
63
|
-
dto[key] = request.body[body_key]
|
|
64
|
-
break
|
|
65
|
-
}
|
|
66
|
-
case 'url':
|
|
67
|
-
{
|
|
68
|
-
const url_index = parseInt(map[key][type])
|
|
69
|
-
dto[key] = request.url.split('/')[url_index]
|
|
70
|
-
break
|
|
71
|
-
}
|
|
72
|
-
case 'query':
|
|
73
|
-
{
|
|
74
|
-
const query_key = map[key][type]
|
|
75
|
-
dto[key] = request.query[query_key]
|
|
76
|
-
break
|
|
77
|
-
}
|
|
78
|
-
default:
|
|
79
|
-
{
|
|
80
|
-
throw new DtoInvalidReferenceError(`type "${type}" is not recognized for request to DTO mapping`)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return dto
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
module.exports = HttpRouteBuilder
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const HttpRouteBuilder = require('.')
|
|
2
|
-
|
|
3
|
-
class HttpRouteBuilderLocator
|
|
4
|
-
{
|
|
5
|
-
constructor(locator)
|
|
6
|
-
{
|
|
7
|
-
this.locator = locator
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
locate()
|
|
11
|
-
{
|
|
12
|
-
const
|
|
13
|
-
deepmerge = this.locator.locate('deepmerge'),
|
|
14
|
-
builder = new HttpRouteBuilder(deepmerge)
|
|
15
|
-
|
|
16
|
-
return builder
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = HttpRouteBuilderLocator
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const Cookies = require('cookies')
|
|
2
|
-
|
|
3
|
-
class SessionBuilder
|
|
4
|
-
{
|
|
5
|
-
build(request, response, domain)
|
|
6
|
-
{
|
|
7
|
-
let cookies
|
|
8
|
-
|
|
9
|
-
const session =
|
|
10
|
-
{
|
|
11
|
-
domain,
|
|
12
|
-
|
|
13
|
-
request,
|
|
14
|
-
|
|
15
|
-
response,
|
|
16
|
-
|
|
17
|
-
set cookies(value)
|
|
18
|
-
{
|
|
19
|
-
throw new Error('"cookies" can not be set on session, protected member')
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
get cookies()
|
|
23
|
-
{
|
|
24
|
-
return cookies
|
|
25
|
-
? cookies
|
|
26
|
-
: cookies = new Cookies(request, response)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return session
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = SessionBuilder
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
class HttpView
|
|
2
|
-
{
|
|
3
|
-
write(output, viewModel)
|
|
4
|
-
{
|
|
5
|
-
viewModel.headers['Content-Length'] = Buffer.byteLength(viewModel.body)
|
|
6
|
-
|
|
7
|
-
output.writeHead(viewModel.meta.status || 200, viewModel.headers)
|
|
8
|
-
output.end(viewModel.body)
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
module.exports = HttpView
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
class HttpViewJson
|
|
2
|
-
{
|
|
3
|
-
write(output, viewModel, route)
|
|
4
|
-
{
|
|
5
|
-
const body = viewModel.meta.pretty || route.pretty
|
|
6
|
-
? JSON.stringify(viewModel.body, null, 2)
|
|
7
|
-
: JSON.stringify(viewModel.body)
|
|
8
|
-
|
|
9
|
-
viewModel.headers['Content-Type'] = 'application/json'
|
|
10
|
-
viewModel.headers['Content-Length'] = Buffer.byteLength(body)
|
|
11
|
-
|
|
12
|
-
output.writeHead(viewModel.meta.status || 200, viewModel.headers)
|
|
13
|
-
output.end(body)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = HttpViewJson
|