@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.
Files changed (175) hide show
  1. package/README.md +108 -739
  2. package/index.js +654 -54
  3. package/index.test.js +94 -0
  4. package/package.json +17 -31
  5. package/worker.js +12 -0
  6. package/LICENCE +0 -20
  7. package/bootstrap/config.js +0 -7
  8. package/bootstrap/index.js +0 -19
  9. package/bootstrap/locator.js +0 -16
  10. package/cli/config.js +0 -7
  11. package/cli/index.js +0 -49
  12. package/cli/locator.js +0 -17
  13. package/composer/bootstrap/error/schema-not-resolvable.js +0 -10
  14. package/composer/bootstrap/index.js +0 -62
  15. package/composer/bootstrap/locator.js +0 -20
  16. package/composer/config.js +0 -49
  17. package/composer/error/filter-is-not-honering-contract.js +0 -13
  18. package/composer/error/invalid-attribute.js +0 -13
  19. package/composer/error/invalid-collection.js +0 -13
  20. package/composer/error/invalid-schema.js +0 -13
  21. package/composer/error/schema-not-found.js +0 -13
  22. package/composer/error/validator-is-not-honering-contract.js +0 -13
  23. package/composer/error/validator-not-found.js +0 -13
  24. package/composer/filter/boolean/index.js +0 -44
  25. package/composer/filter/boolean/locator.js +0 -11
  26. package/composer/filter/decimal/index.js +0 -38
  27. package/composer/filter/decimal/locator.js +0 -11
  28. package/composer/filter/index.js +0 -10
  29. package/composer/filter/integer/index.js +0 -38
  30. package/composer/filter/integer/locator.js +0 -11
  31. package/composer/filter/json/index.js +0 -23
  32. package/composer/filter/json/locator.js +0 -11
  33. package/composer/filter/schema/error/missing-schema-definition.js +0 -13
  34. package/composer/filter/schema/index.js +0 -49
  35. package/composer/filter/schema/locator.js +0 -17
  36. package/composer/filter/string/index.js +0 -50
  37. package/composer/filter/string/locator.js +0 -11
  38. package/composer/filter/timestamp/index.js +0 -45
  39. package/composer/filter/timestamp/locator.js +0 -11
  40. package/composer/index.js +0 -180
  41. package/composer/locator.js +0 -17
  42. package/composer/validator/boolean/error/invalid.js +0 -13
  43. package/composer/validator/boolean/index.js +0 -17
  44. package/composer/validator/boolean/locator.js +0 -11
  45. package/composer/validator/decimal/error/invalid.js +0 -13
  46. package/composer/validator/decimal/index.js +0 -59
  47. package/composer/validator/decimal/locator.js +0 -11
  48. package/composer/validator/index.js +0 -10
  49. package/composer/validator/integer/error/invalid.js +0 -13
  50. package/composer/validator/integer/index.js +0 -65
  51. package/composer/validator/integer/locator.js +0 -11
  52. package/composer/validator/json/error/invalid.js +0 -13
  53. package/composer/validator/json/index.js +0 -23
  54. package/composer/validator/json/locator.js +0 -11
  55. package/composer/validator/schema/error/invalid.js +0 -13
  56. package/composer/validator/schema/index.js +0 -13
  57. package/composer/validator/schema/locator.js +0 -11
  58. package/composer/validator/string/error/invalid.js +0 -13
  59. package/composer/validator/string/index.js +0 -59
  60. package/composer/validator/string/locator.js +0 -11
  61. package/composer/validator/timestamp/error/invalid.js +0 -13
  62. package/composer/validator/timestamp/index.js +0 -54
  63. package/composer/validator/timestamp/locator.js +0 -11
  64. package/configuration/config.js +0 -7
  65. package/configuration/index.js +0 -23
  66. package/configuration/locator.js +0 -22
  67. package/console/config.js +0 -15
  68. package/console/index.js +0 -23
  69. package/console/locator.js +0 -21
  70. package/console/observer/error/config.js +0 -7
  71. package/console/observer/error/index.js +0 -14
  72. package/console/observer/error/locator.js +0 -17
  73. package/console/observer/info/config.js +0 -7
  74. package/console/observer/info/index.js +0 -14
  75. package/console/observer/info/locator.js +0 -17
  76. package/console/observer/warning/config.js +0 -7
  77. package/console/observer/warning/index.js +0 -14
  78. package/console/observer/warning/locator.js +0 -17
  79. package/core/config.js +0 -21
  80. package/core/error.js +0 -10
  81. package/deepcopy/config.js +0 -7
  82. package/deepcopy/error/failed-to-fast-copy.js +0 -10
  83. package/deepcopy/index.js +0 -18
  84. package/deepcopy/locator.js +0 -11
  85. package/deepfind/config.js +0 -7
  86. package/deepfind/index.js +0 -11
  87. package/deepfind/locator.js +0 -11
  88. package/deepfreeze/config.js +0 -7
  89. package/deepfreeze/index.js +0 -20
  90. package/deepfreeze/locator.js +0 -11
  91. package/deepmerge/config.js +0 -7
  92. package/deepmerge/index.js +0 -42
  93. package/deepmerge/locator.js +0 -11
  94. package/eventbus/bootstrap/error/observer-contract-not-honered.js +0 -10
  95. package/eventbus/bootstrap/index.js +0 -33
  96. package/eventbus/bootstrap/locator.js +0 -20
  97. package/eventbus/config.js +0 -17
  98. package/eventbus/index.js +0 -21
  99. package/eventbus/locator.js +0 -25
  100. package/eventbus/observer.js +0 -9
  101. package/factory.js +0 -55
  102. package/http/request/config.js +0 -7
  103. package/http/request/locator.js +0 -21
  104. package/http/server/config.js +0 -23
  105. package/http/server/dispatcher/chain/error/dispatcher-chain-ended.js +0 -10
  106. package/http/server/dispatcher/chain/index.js +0 -41
  107. package/http/server/dispatcher/chain/locator.js +0 -20
  108. package/http/server/dispatcher/collection/builder/error/dispatcher-can-not-be-resolved.js +0 -10
  109. package/http/server/dispatcher/collection/builder/error/not-honering-dispatcher-contract.js +0 -10
  110. package/http/server/dispatcher/collection/builder/index.js +0 -56
  111. package/http/server/dispatcher/collection/builder/locator.js +0 -20
  112. package/http/server/dispatcher/error/bad-gateway.js +0 -12
  113. package/http/server/dispatcher/error/bad-request.js +0 -12
  114. package/http/server/dispatcher/error/conflict.js +0 -12
  115. package/http/server/dispatcher/error/forbidden.js +0 -12
  116. package/http/server/dispatcher/error/gateway-timeout.js +0 -12
  117. package/http/server/dispatcher/error/index.js +0 -10
  118. package/http/server/dispatcher/error/method-not-allowed.js +0 -12
  119. package/http/server/dispatcher/error/not-implemented.js +0 -12
  120. package/http/server/dispatcher/error/page-not-found.js +0 -12
  121. package/http/server/dispatcher/error/request-timeout.js +0 -12
  122. package/http/server/dispatcher/error/server-error.js +0 -12
  123. package/http/server/dispatcher/error/service-unavailable.js +0 -12
  124. package/http/server/dispatcher/error/unauthorized.js +0 -12
  125. package/http/server/dispatcher/index.js +0 -26
  126. package/http/server/dispatcher/rest.js +0 -75
  127. package/http/server/error/no-endpoint-defined-in-route.js +0 -10
  128. package/http/server/error/view-contract-not-honered.js +0 -10
  129. package/http/server/index.js +0 -195
  130. package/http/server/locator.js +0 -34
  131. package/http/server/request/builder/index.js +0 -53
  132. package/http/server/request/builder/locator.js +0 -20
  133. package/http/server/route/builder/error/dto-invalid-reference.js +0 -10
  134. package/http/server/route/builder/error/routes-invalid-type.js +0 -10
  135. package/http/server/route/builder/index.js +0 -88
  136. package/http/server/route/builder/locator.js +0 -20
  137. package/http/server/session/builder/index.js +0 -34
  138. package/http/server/session/builder/locator.js +0 -11
  139. package/http/server/view/index.js +0 -12
  140. package/http/server/view/json/index.js +0 -17
  141. package/http/server/view/json/locator.js +0 -11
  142. package/http/server/view/locator.js +0 -11
  143. package/http/server/view/stream/index.js +0 -10
  144. package/http/server/view/stream/locator.js +0 -11
  145. package/http/server/view/text/index.js +0 -15
  146. package/http/server/view/text/locator.js +0 -11
  147. package/locator/constituent.js +0 -26
  148. package/locator/error/locator-not-implemented.js +0 -10
  149. package/locator/error/service-undefined.js +0 -10
  150. package/locator/index.js +0 -29
  151. package/path/config.js +0 -7
  152. package/path/index.js +0 -63
  153. package/path/locator.js +0 -11
  154. package/process/bootstrap/index.js +0 -31
  155. package/process/bootstrap/locator.js +0 -17
  156. package/process/config.js +0 -12
  157. package/process/index.js +0 -9
  158. package/process/locator.js +0 -11
  159. package/test/api/config.js +0 -43
  160. package/test/api/endpoint/append-calculation.js +0 -41
  161. package/test/api/endpoint/create-calculation.js +0 -18
  162. package/test/api/middleware/authentication.js +0 -27
  163. package/test/calculator/calculation.js +0 -29
  164. package/test/calculator/config.js +0 -14
  165. package/test/calculator/error/calculation-could-not-be-found.js +0 -13
  166. package/test/calculator/error/invalid-calculation-type.js +0 -13
  167. package/test/calculator/index.js +0 -67
  168. package/test/calculator/locator.js +0 -20
  169. package/test/init.js +0 -2
  170. package/test/logger/config.js +0 -15
  171. package/test/logger/index.js +0 -17
  172. package/test/logger/locator.js +0 -20
  173. package/test/mocha.opts +0 -4
  174. package/test/test.calculation.js +0 -58
  175. package/test/test.logger.js +0 -35
@@ -1,12 +0,0 @@
1
- const HttpError = require('.')
2
-
3
- class RequestTimeout extends HttpError
4
- {
5
- constructor(...args)
6
- {
7
- super(...args)
8
- this.status = 408
9
- }
10
- }
11
-
12
- module.exports = RequestTimeout
@@ -1,12 +0,0 @@
1
- const HttpError = require('.')
2
-
3
- class ServerError extends HttpError
4
- {
5
- constructor(...args)
6
- {
7
- super(...args)
8
- this.status = 500
9
- }
10
- }
11
-
12
- module.exports = ServerError
@@ -1,12 +0,0 @@
1
- const HttpError = require('.')
2
-
3
- class ServiceUnavailable extends HttpError
4
- {
5
- constructor(...args)
6
- {
7
- super(...args)
8
- this.status = 503
9
- }
10
- }
11
-
12
- module.exports = ServiceUnavailable
@@ -1,12 +0,0 @@
1
- const HttpError = require('.')
2
-
3
- class Unauthorized extends HttpError
4
- {
5
- constructor(...args)
6
- {
7
- super(...args)
8
- this.status = 401
9
- }
10
- }
11
-
12
- module.exports = Unauthorized
@@ -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
@@ -1,10 +0,0 @@
1
- class NoEndpointDefinedInRouteError extends Error
2
- {
3
- constructor(...args)
4
- {
5
- super(...args)
6
- this.code = 'E_NO_ENDPOINT_DEFINED_IN_ROUTE'
7
- }
8
- }
9
-
10
- module.exports = NoEndpointDefinedInRouteError
@@ -1,10 +0,0 @@
1
- class ViewContractNotHoneredError extends Error
2
- {
3
- constructor(...args)
4
- {
5
- super(...args)
6
- this.code = 'E_VIEW_CONTRACT_NOT_HONERED'
7
- }
8
- }
9
-
10
- module.exports = ViewContractNotHoneredError
@@ -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
@@ -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,10 +0,0 @@
1
- class DtoInvalidReferenceError extends ReferenceError
2
- {
3
- constructor(...args)
4
- {
5
- super(...args)
6
- this.code = 'E_DTO_INVALID_REFERENCE'
7
- }
8
- }
9
-
10
- module.exports = DtoInvalidReferenceError
@@ -1,10 +0,0 @@
1
- class RoutesInvalidTypeError extends TypeError
2
- {
3
- constructor(...args)
4
- {
5
- super(...args)
6
- this.code = 'E_ROUTES_INVALID_TYPE'
7
- }
8
- }
9
-
10
- module.exports = RoutesInvalidTypeError
@@ -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,11 +0,0 @@
1
- const SessionBuilder = require('.')
2
-
3
- class SessionBuilderLocator
4
- {
5
- locate()
6
- {
7
- return new SessionBuilder
8
- }
9
- }
10
-
11
- module.exports = SessionBuilderLocator
@@ -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