@toa.io/extensions.exposition 0.8.3-dev.9 → 0.20.0-alpha.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.
Files changed (363) hide show
  1. package/components/context.toa.yaml +15 -0
  2. package/components/identity.bans/manifest.toa.yaml +18 -0
  3. package/components/identity.basic/events/principal.js +9 -0
  4. package/components/identity.basic/manifest.toa.yaml +50 -0
  5. package/components/identity.basic/source/authenticate.ts +29 -0
  6. package/components/identity.basic/source/create.ts +19 -0
  7. package/components/identity.basic/source/transit.ts +64 -0
  8. package/components/identity.basic/source/types.ts +42 -0
  9. package/components/identity.basic/tsconfig.json +9 -0
  10. package/components/identity.roles/manifest.toa.yaml +31 -0
  11. package/components/identity.roles/source/list.ts +7 -0
  12. package/components/identity.roles/source/principal.ts +20 -0
  13. package/components/identity.roles/tsconfig.json +9 -0
  14. package/components/identity.tokens/manifest.toa.yaml +39 -0
  15. package/components/identity.tokens/receivers/identity.bans.updated.js +3 -0
  16. package/components/identity.tokens/source/authenticate.test.ts +56 -0
  17. package/components/identity.tokens/source/authenticate.ts +38 -0
  18. package/components/identity.tokens/source/decrypt.test.ts +59 -0
  19. package/components/identity.tokens/source/decrypt.ts +25 -0
  20. package/components/identity.tokens/source/encrypt.test.ts +35 -0
  21. package/components/identity.tokens/source/encrypt.ts +25 -0
  22. package/components/identity.tokens/source/revoke.ts +5 -0
  23. package/components/identity.tokens/source/types.ts +48 -0
  24. package/components/identity.tokens/tsconfig.json +9 -0
  25. package/cucumber.js +9 -0
  26. package/documentation/.assets/ia3-dark.jpg +0 -0
  27. package/documentation/.assets/ia3-light.jpg +0 -0
  28. package/documentation/.assets/overview-dark.jpg +0 -0
  29. package/documentation/.assets/overview-light.jpg +0 -0
  30. package/documentation/.assets/role-scopes-dark.jpg +0 -0
  31. package/documentation/.assets/role-scopes-light.jpg +0 -0
  32. package/documentation/.assets/rtd-dark.jpg +0 -0
  33. package/documentation/.assets/rtd-light.jpg +0 -0
  34. package/documentation/access.md +256 -0
  35. package/documentation/components.md +276 -0
  36. package/documentation/identity.md +156 -0
  37. package/documentation/protocol.md +15 -0
  38. package/documentation/query.md +226 -0
  39. package/documentation/tree.md +169 -0
  40. package/features/access.feature +442 -0
  41. package/features/annotation.feature +28 -0
  42. package/features/body.feature +21 -0
  43. package/features/directives.feature +56 -0
  44. package/features/dynamic.feature +89 -0
  45. package/features/errors.feature +208 -0
  46. package/features/identity.basic.feature +235 -0
  47. package/features/identity.feature +61 -0
  48. package/features/identity.roles.feature +51 -0
  49. package/features/identity.tokens.feature +116 -0
  50. package/features/queries.feature +214 -0
  51. package/features/routes.feature +49 -0
  52. package/features/steps/Common.ts +10 -0
  53. package/features/steps/Components.ts +43 -0
  54. package/features/steps/Database.ts +58 -0
  55. package/features/steps/Gateway.ts +105 -0
  56. package/features/steps/HTTP.ts +71 -0
  57. package/features/steps/Parameters.ts +12 -0
  58. package/features/steps/Workspace.ts +40 -0
  59. package/features/steps/components/greeter/manifest.toa.yaml +9 -0
  60. package/features/steps/components/greeter/operations/greet.js +7 -0
  61. package/features/steps/components/pots/manifest.toa.yaml +20 -0
  62. package/features/steps/components/users/manifest.toa.yaml +11 -0
  63. package/features/steps/tsconfig.json +9 -0
  64. package/package.json +31 -17
  65. package/readme.md +181 -0
  66. package/schemas/annotation.cos.yaml +4 -0
  67. package/schemas/directive.cos.yaml +3 -0
  68. package/schemas/method.cos.yaml +9 -0
  69. package/schemas/node.cos.yaml +5 -0
  70. package/schemas/query.cos.yaml +16 -0
  71. package/schemas/querystring.cos.yaml +5 -0
  72. package/schemas/range.cos.yaml +2 -0
  73. package/schemas/route.cos.yaml +2 -0
  74. package/source/Annotation.ts +6 -0
  75. package/source/Branch.ts +8 -0
  76. package/source/Composition.ts +58 -0
  77. package/source/Context.ts +6 -0
  78. package/source/Directive.test.ts +91 -0
  79. package/source/Directive.ts +120 -0
  80. package/source/Endpoint.ts +57 -0
  81. package/source/Factory.ts +53 -0
  82. package/source/Gateway.ts +93 -0
  83. package/source/HTTP/Server.fixtures.ts +45 -0
  84. package/source/HTTP/Server.test.ts +221 -0
  85. package/source/HTTP/Server.ts +135 -0
  86. package/source/HTTP/exceptions.ts +77 -0
  87. package/source/HTTP/formats/index.ts +19 -0
  88. package/source/HTTP/formats/json.ts +13 -0
  89. package/source/HTTP/formats/msgpack.ts +10 -0
  90. package/source/HTTP/formats/text.ts +9 -0
  91. package/source/HTTP/formats/yaml.ts +14 -0
  92. package/source/HTTP/index.ts +3 -0
  93. package/source/HTTP/messages.test.ts +116 -0
  94. package/source/HTTP/messages.ts +77 -0
  95. package/source/Mapping.ts +48 -0
  96. package/source/Query.test.ts +37 -0
  97. package/source/Query.ts +105 -0
  98. package/source/RTD/Context.ts +16 -0
  99. package/source/RTD/Directives.ts +9 -0
  100. package/source/RTD/Endpoint.ts +11 -0
  101. package/source/RTD/Match.ts +16 -0
  102. package/source/RTD/Method.ts +24 -0
  103. package/source/RTD/Node.ts +85 -0
  104. package/source/RTD/Route.ts +58 -0
  105. package/source/RTD/Tree.ts +57 -0
  106. package/source/RTD/factory.ts +47 -0
  107. package/source/RTD/index.ts +8 -0
  108. package/source/RTD/segment.test.ts +32 -0
  109. package/source/RTD/segment.ts +25 -0
  110. package/source/RTD/syntax/index.ts +2 -0
  111. package/source/RTD/syntax/parse.test.ts +188 -0
  112. package/source/RTD/syntax/parse.ts +153 -0
  113. package/source/RTD/syntax/types.ts +48 -0
  114. package/source/Remotes.test.ts +41 -0
  115. package/source/Remotes.ts +20 -0
  116. package/source/Tenant.ts +38 -0
  117. package/source/deployment.ts +42 -0
  118. package/source/directives/auth/Anonymous.ts +14 -0
  119. package/source/directives/auth/Echo.ts +12 -0
  120. package/source/directives/auth/Family.ts +145 -0
  121. package/source/directives/auth/Id.ts +19 -0
  122. package/source/directives/auth/Incept.ts +42 -0
  123. package/source/directives/auth/Role.test.ts +62 -0
  124. package/source/directives/auth/Role.ts +56 -0
  125. package/source/directives/auth/Rule.ts +28 -0
  126. package/source/directives/auth/Scheme.ts +26 -0
  127. package/source/directives/auth/index.ts +3 -0
  128. package/source/directives/auth/schemes.ts +8 -0
  129. package/source/directives/auth/split.ts +15 -0
  130. package/source/directives/auth/types.ts +37 -0
  131. package/source/directives/dev/Family.ts +34 -0
  132. package/source/directives/dev/Stub.ts +14 -0
  133. package/source/directives/dev/index.ts +3 -0
  134. package/source/directives/dev/types.ts +5 -0
  135. package/source/directives/index.ts +5 -0
  136. package/source/discovery.ts +1 -0
  137. package/source/exceptions.ts +17 -0
  138. package/source/index.test.ts +9 -0
  139. package/source/index.ts +6 -0
  140. package/source/manifest.test.ts +57 -0
  141. package/source/manifest.ts +35 -0
  142. package/source/root.ts +38 -0
  143. package/source/schemas.ts +9 -0
  144. package/transpiled/Annotation.d.ts +6 -0
  145. package/transpiled/Annotation.js +3 -0
  146. package/transpiled/Annotation.js.map +1 -0
  147. package/transpiled/Branch.d.ts +7 -0
  148. package/transpiled/Branch.js +3 -0
  149. package/transpiled/Branch.js.map +1 -0
  150. package/transpiled/Composition.d.ts +14 -0
  151. package/transpiled/Composition.js +43 -0
  152. package/transpiled/Composition.js.map +1 -0
  153. package/transpiled/Context.d.ts +5 -0
  154. package/transpiled/Context.js +3 -0
  155. package/transpiled/Context.js.map +1 -0
  156. package/transpiled/Directive.d.ts +32 -0
  157. package/transpiled/Directive.js +76 -0
  158. package/transpiled/Directive.js.map +1 -0
  159. package/transpiled/Endpoint.d.ts +20 -0
  160. package/transpiled/Endpoint.js +44 -0
  161. package/transpiled/Endpoint.js.map +1 -0
  162. package/transpiled/Factory.d.ts +11 -0
  163. package/transpiled/Factory.js +67 -0
  164. package/transpiled/Factory.js.map +1 -0
  165. package/transpiled/Gateway.d.ts +19 -0
  166. package/transpiled/Gateway.js +90 -0
  167. package/transpiled/Gateway.js.map +1 -0
  168. package/transpiled/HTTP/Server.d.ts +22 -0
  169. package/transpiled/HTTP/Server.fixtures.d.ts +12 -0
  170. package/transpiled/HTTP/Server.fixtures.js +36 -0
  171. package/transpiled/HTTP/Server.fixtures.js.map +1 -0
  172. package/transpiled/HTTP/Server.js +111 -0
  173. package/transpiled/HTTP/Server.js.map +1 -0
  174. package/transpiled/HTTP/exceptions.d.ts +39 -0
  175. package/transpiled/HTTP/exceptions.js +78 -0
  176. package/transpiled/HTTP/exceptions.js.map +1 -0
  177. package/transpiled/HTTP/formats/index.d.ts +8 -0
  178. package/transpiled/HTTP/formats/index.js +38 -0
  179. package/transpiled/HTTP/formats/index.js.map +1 -0
  180. package/transpiled/HTTP/formats/json.d.ts +4 -0
  181. package/transpiled/HTTP/formats/json.js +15 -0
  182. package/transpiled/HTTP/formats/json.js.map +1 -0
  183. package/transpiled/HTTP/formats/msgpack.d.ts +4 -0
  184. package/transpiled/HTTP/formats/msgpack.js +36 -0
  185. package/transpiled/HTTP/formats/msgpack.js.map +1 -0
  186. package/transpiled/HTTP/formats/text.d.ts +4 -0
  187. package/transpiled/HTTP/formats/text.js +13 -0
  188. package/transpiled/HTTP/formats/text.js.map +1 -0
  189. package/transpiled/HTTP/formats/yaml.d.ts +4 -0
  190. package/transpiled/HTTP/formats/yaml.js +39 -0
  191. package/transpiled/HTTP/formats/yaml.js.map +1 -0
  192. package/transpiled/HTTP/index.d.ts +3 -0
  193. package/transpiled/HTTP/index.js +20 -0
  194. package/transpiled/HTTP/index.js.map +1 -0
  195. package/transpiled/HTTP/messages.d.ts +27 -0
  196. package/transpiled/HTTP/messages.js +49 -0
  197. package/transpiled/HTTP/messages.js.map +1 -0
  198. package/transpiled/Mapping.d.ts +8 -0
  199. package/transpiled/Mapping.js +35 -0
  200. package/transpiled/Mapping.js.map +1 -0
  201. package/transpiled/Query.d.ts +13 -0
  202. package/transpiled/Query.js +107 -0
  203. package/transpiled/Query.js.map +1 -0
  204. package/transpiled/RTD/Context.d.ts +11 -0
  205. package/transpiled/RTD/Context.js +3 -0
  206. package/transpiled/RTD/Context.js.map +1 -0
  207. package/transpiled/RTD/Directives.d.ts +7 -0
  208. package/transpiled/RTD/Directives.js +3 -0
  209. package/transpiled/RTD/Directives.js.map +1 -0
  210. package/transpiled/RTD/Endpoint.d.ts +9 -0
  211. package/transpiled/RTD/Endpoint.js +3 -0
  212. package/transpiled/RTD/Endpoint.js.map +1 -0
  213. package/transpiled/RTD/Match.d.ts +11 -0
  214. package/transpiled/RTD/Match.js +3 -0
  215. package/transpiled/RTD/Match.js.map +1 -0
  216. package/transpiled/RTD/Method.d.ts +9 -0
  217. package/transpiled/RTD/Method.js +16 -0
  218. package/transpiled/RTD/Method.js.map +1 -0
  219. package/transpiled/RTD/Node.d.ts +21 -0
  220. package/transpiled/RTD/Node.js +61 -0
  221. package/transpiled/RTD/Node.js.map +1 -0
  222. package/transpiled/RTD/Route.d.ts +14 -0
  223. package/transpiled/RTD/Route.js +48 -0
  224. package/transpiled/RTD/Route.js.map +1 -0
  225. package/transpiled/RTD/Tree.d.ts +14 -0
  226. package/transpiled/RTD/Tree.js +45 -0
  227. package/transpiled/RTD/Tree.js.map +1 -0
  228. package/transpiled/RTD/factory.d.ts +6 -0
  229. package/transpiled/RTD/factory.js +36 -0
  230. package/transpiled/RTD/factory.js.map +1 -0
  231. package/transpiled/RTD/index.d.ts +8 -0
  232. package/transpiled/RTD/index.js +38 -0
  233. package/transpiled/RTD/index.js.map +1 -0
  234. package/transpiled/RTD/segment.d.ts +8 -0
  235. package/transpiled/RTD/segment.js +23 -0
  236. package/transpiled/RTD/segment.js.map +1 -0
  237. package/transpiled/RTD/syntax/index.d.ts +2 -0
  238. package/transpiled/RTD/syntax/index.js +19 -0
  239. package/transpiled/RTD/syntax/index.js.map +1 -0
  240. package/transpiled/RTD/syntax/parse.d.ts +4 -0
  241. package/transpiled/RTD/syntax/parse.js +128 -0
  242. package/transpiled/RTD/syntax/parse.js.map +1 -0
  243. package/transpiled/RTD/syntax/types.d.ts +41 -0
  244. package/transpiled/RTD/syntax/types.js +5 -0
  245. package/transpiled/RTD/syntax/types.js.map +1 -0
  246. package/transpiled/Remotes.d.ts +7 -0
  247. package/transpiled/Remotes.js +19 -0
  248. package/transpiled/Remotes.js.map +1 -0
  249. package/transpiled/Tenant.d.ts +12 -0
  250. package/transpiled/Tenant.js +30 -0
  251. package/transpiled/Tenant.js.map +1 -0
  252. package/transpiled/deployment.d.ts +3 -0
  253. package/transpiled/deployment.js +61 -0
  254. package/transpiled/deployment.js.map +1 -0
  255. package/transpiled/directives/auth/Anonymous.d.ts +6 -0
  256. package/transpiled/directives/auth/Anonymous.js +17 -0
  257. package/transpiled/directives/auth/Anonymous.js.map +1 -0
  258. package/transpiled/directives/auth/Echo.d.ts +6 -0
  259. package/transpiled/directives/auth/Echo.js +13 -0
  260. package/transpiled/directives/auth/Echo.js.map +1 -0
  261. package/transpiled/directives/auth/Family.d.ts +20 -0
  262. package/transpiled/directives/auth/Family.js +125 -0
  263. package/transpiled/directives/auth/Family.js.map +1 -0
  264. package/transpiled/directives/auth/Id.d.ts +7 -0
  265. package/transpiled/directives/auth/Id.js +17 -0
  266. package/transpiled/directives/auth/Id.js.map +1 -0
  267. package/transpiled/directives/auth/Incept.d.ts +10 -0
  268. package/transpiled/directives/auth/Incept.js +59 -0
  269. package/transpiled/directives/auth/Incept.js.map +1 -0
  270. package/transpiled/directives/auth/Role.d.ts +11 -0
  271. package/transpiled/directives/auth/Role.js +44 -0
  272. package/transpiled/directives/auth/Role.js.map +1 -0
  273. package/transpiled/directives/auth/Rule.d.ts +9 -0
  274. package/transpiled/directives/auth/Rule.js +22 -0
  275. package/transpiled/directives/auth/Rule.js.map +1 -0
  276. package/transpiled/directives/auth/Scheme.d.ts +7 -0
  277. package/transpiled/directives/auth/Scheme.js +47 -0
  278. package/transpiled/directives/auth/Scheme.js.map +1 -0
  279. package/transpiled/directives/auth/index.d.ts +2 -0
  280. package/transpiled/directives/auth/index.js +7 -0
  281. package/transpiled/directives/auth/index.js.map +1 -0
  282. package/transpiled/directives/auth/schemes.d.ts +3 -0
  283. package/transpiled/directives/auth/schemes.js +9 -0
  284. package/transpiled/directives/auth/schemes.js.map +1 -0
  285. package/transpiled/directives/auth/split.d.ts +2 -0
  286. package/transpiled/directives/auth/split.js +38 -0
  287. package/transpiled/directives/auth/split.js.map +1 -0
  288. package/transpiled/directives/auth/types.d.ts +31 -0
  289. package/transpiled/directives/auth/types.js +3 -0
  290. package/transpiled/directives/auth/types.js.map +1 -0
  291. package/transpiled/directives/dev/Family.d.ts +10 -0
  292. package/transpiled/directives/dev/Family.js +25 -0
  293. package/transpiled/directives/dev/Family.js.map +1 -0
  294. package/transpiled/directives/dev/Stub.d.ts +7 -0
  295. package/transpiled/directives/dev/Stub.js +14 -0
  296. package/transpiled/directives/dev/Stub.js.map +1 -0
  297. package/transpiled/directives/dev/index.d.ts +2 -0
  298. package/transpiled/directives/dev/index.js +7 -0
  299. package/transpiled/directives/dev/index.js.map +1 -0
  300. package/transpiled/directives/dev/types.d.ts +4 -0
  301. package/transpiled/directives/dev/types.js +3 -0
  302. package/transpiled/directives/dev/types.js.map +1 -0
  303. package/transpiled/directives/index.d.ts +2 -0
  304. package/transpiled/directives/index.js +10 -0
  305. package/transpiled/directives/index.js.map +1 -0
  306. package/transpiled/discovery.d.ts +1 -0
  307. package/transpiled/discovery.js +3 -0
  308. package/transpiled/discovery.js.map +1 -0
  309. package/transpiled/exceptions.d.ts +2 -0
  310. package/transpiled/exceptions.js +39 -0
  311. package/transpiled/exceptions.js.map +1 -0
  312. package/transpiled/index.d.ts +5 -0
  313. package/transpiled/index.js +12 -0
  314. package/transpiled/index.js.map +1 -0
  315. package/transpiled/manifest.d.ts +3 -0
  316. package/transpiled/manifest.js +30 -0
  317. package/transpiled/manifest.js.map +1 -0
  318. package/transpiled/root.d.ts +2 -0
  319. package/transpiled/root.js +39 -0
  320. package/transpiled/root.js.map +1 -0
  321. package/transpiled/schemas.d.ts +3 -0
  322. package/transpiled/schemas.js +14 -0
  323. package/transpiled/schemas.js.map +1 -0
  324. package/transpiled/tsconfig.tsbuildinfo +1 -0
  325. package/tsconfig.json +12 -0
  326. package/src/.manifest/index.js +0 -7
  327. package/src/.manifest/normalize.js +0 -58
  328. package/src/.manifest/schema.yaml +0 -69
  329. package/src/.manifest/validate.js +0 -17
  330. package/src/constants.js +0 -3
  331. package/src/deployment.js +0 -23
  332. package/src/exposition.js +0 -68
  333. package/src/factory.js +0 -76
  334. package/src/index.js +0 -9
  335. package/src/manifest.js +0 -12
  336. package/src/query/criteria.js +0 -55
  337. package/src/query/enum.js +0 -35
  338. package/src/query/index.js +0 -17
  339. package/src/query/query.js +0 -60
  340. package/src/query/range.js +0 -28
  341. package/src/query/sort.js +0 -19
  342. package/src/remote.js +0 -88
  343. package/src/server.js +0 -83
  344. package/src/tenant.js +0 -29
  345. package/src/translate/etag.js +0 -14
  346. package/src/translate/index.js +0 -7
  347. package/src/translate/request.js +0 -68
  348. package/src/translate/response.js +0 -62
  349. package/src/tree.js +0 -109
  350. package/test/manifest.normalize.fixtures.js +0 -37
  351. package/test/manifest.normalize.test.js +0 -37
  352. package/test/manifest.validate.test.js +0 -40
  353. package/test/query.range.test.js +0 -18
  354. package/test/tree.fixtures.js +0 -21
  355. package/test/tree.test.js +0 -44
  356. package/types/annotations.d.ts +0 -10
  357. package/types/declarations.d.ts +0 -31
  358. package/types/exposition.d.ts +0 -13
  359. package/types/http.d.ts +0 -13
  360. package/types/query.d.ts +0 -16
  361. package/types/remote.d.ts +0 -19
  362. package/types/server.d.ts +0 -13
  363. package/types/tree.d.ts +0 -33
@@ -1,60 +0,0 @@
1
- 'use strict'
2
-
3
- const { merge } = require('@toa.io/generic')
4
-
5
- /**
6
- * @implements {toa.extensions.exposition.Query}
7
- */
8
- class Query {
9
- #constraints
10
-
11
- constructor (constraints) {
12
- this.#constraints = Object.entries(constraints)
13
- }
14
-
15
- /** @hot */
16
- parse (query, operation) {
17
- for (const [key, constraint] of this.#constraints) {
18
- const value = constraint.parse(query?.[key], operation)
19
-
20
- if (value !== undefined) {
21
- if (query === undefined) query = {}
22
-
23
- query[key] = value
24
- }
25
- }
26
-
27
- return query
28
- }
29
-
30
- /**
31
- * @param {toa.extensions.exposition.declarations.Node} node
32
- * @returns {toa.extensions.exposition.declarations.Query}
33
- */
34
- static merge (node) {
35
- const query = {}
36
- let current = node
37
-
38
- do {
39
- if (current.query !== undefined) merge(query, current.query, { ignore: true })
40
-
41
- current = current.parent
42
- } while (current !== undefined)
43
-
44
- merge(query, DEFAULTS, { ignore: true })
45
-
46
- return query
47
- }
48
- }
49
-
50
- const DEFAULTS = {
51
- omit: {
52
- range: [0, 1000]
53
- },
54
- limit: {
55
- value: 100,
56
- range: [1, 100]
57
- }
58
- }
59
-
60
- exports.Query = Query
@@ -1,28 +0,0 @@
1
- 'use strict'
2
-
3
- const { exceptions: { RequestConflictException } } = require('@toa.io/core')
4
-
5
- class Range {
6
- #value
7
- #min
8
- #max
9
-
10
- constructor (constraint) {
11
- this.#value = constraint.value
12
-
13
- this.#min = constraint.range[0] === undefined ? this.#value : constraint.range[0]
14
- this.#max = constraint.range[1] === undefined ? this.#value : constraint.range[1]
15
- }
16
-
17
- /** @hot */
18
- parse (value, operation) {
19
- if (operation.type !== 'observation' || operation.scope !== 'objects') return value
20
- if (value === undefined) return this.#value
21
-
22
- if (value > this.#max || value < this.#min) {
23
- throw new RequestConflictException(`Query omit/limit value is out of range [${this.#min}, ${this.#max}]`)
24
- }
25
- }
26
- }
27
-
28
- exports.Range = Range
package/src/query/sort.js DELETED
@@ -1,19 +0,0 @@
1
- 'use strict'
2
-
3
- class Sort {
4
- #value
5
-
6
- constructor (value) {
7
- this.#value = value
8
- }
9
-
10
- /** @hot */
11
- parse (value, operation) {
12
- if (operation.query === false) return value
13
-
14
- if (value === undefined) return this.#value
15
- else return this.#value.concat(value)
16
- }
17
- }
18
-
19
- exports.Sort = Sort
package/src/remote.js DELETED
@@ -1,88 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector, exceptions: { NotImplementedException } } = require('@toa.io/core')
4
- const { console } = require('@toa.io/console')
5
-
6
- const translate = require('./translate')
7
-
8
- /**
9
- * @implements {toa.extensions.exposition.Remote}
10
- */
11
- class Remote extends Connector {
12
- /** @type {toa.core.Component} */
13
- #remote
14
-
15
- /** @type {toa.extensions.exposition.Tree} */
16
- #tree
17
-
18
- /**
19
- * @param {toa.extensions.exposition.Server} server
20
- * @param {toa.core.Component} remote
21
- * @param {toa.extensions.exposition.Tree} tree
22
- */
23
- constructor (server, remote, tree) {
24
- super()
25
-
26
- const { namespace, name } = remote.locator
27
- const route = '/' + (namespace === 'default' ? '' : namespace + '/') + name + '*'
28
-
29
- server.route(route, (req, res) => this.#reply(req, res))
30
-
31
- this.#remote = remote
32
- this.#tree = tree
33
-
34
- this.depends(server)
35
- this.depends(remote)
36
- }
37
-
38
- update (declaration) {
39
- console.info(`Updating tree '${this.#remote.locator.id}'`)
40
-
41
- this.#tree.update(declaration)
42
- }
43
-
44
- /**
45
- * @hot
46
- * @param {toa.extensions.exposition.http.Request} req
47
- * @param {toa.extensions.exposition.http.Response} res
48
- * @return {Promise<void>}
49
- */
50
- async #reply (req, res) {
51
- const match = this.#tree.match(req.params[0])
52
-
53
- if (match !== undefined) {
54
- try {
55
- const reply = await this.#call(req, match)
56
-
57
- translate.response.ok(reply, res, req)
58
- } catch (e) {
59
- translate.response.exception(e, res)
60
- }
61
- } else {
62
- translate.response.missed(res)
63
- }
64
-
65
- res.end()
66
- }
67
-
68
- /**
69
- * @param {toa.extensions.exposition.http.Request} req
70
- * @param {toa.extensions.exposition.tree.Match} match
71
- * @return {Promise<toa.core.Reply>}
72
- */
73
- async #call (req, match) {
74
- const method = req.method === 'HEAD' ? 'GET' : req.method
75
- const operation = match.node.operations[method]
76
-
77
- if (operation === undefined) throw new NotImplementedException()
78
-
79
- const request = translate.request(req, match.params)
80
- const query = match.node.query.parse(request.query, operation)
81
-
82
- if (query !== undefined) request.query = query
83
-
84
- return this.#remote.invoke(operation.operation, request)
85
- }
86
- }
87
-
88
- exports.Remote = Remote
package/src/server.js DELETED
@@ -1,83 +0,0 @@
1
- 'use strict'
2
-
3
- const express = require('express')
4
- const cors = require('cors')
5
-
6
- const { Connector } = require('@toa.io/core')
7
- const { console } = require('@toa.io/console')
8
-
9
- const { PORT } = require('./constants')
10
-
11
- // noinspection JSClosureCompilerSyntax
12
- /**
13
- * @implements {toa.extensions.exposition.Server}
14
- */
15
- class Server extends Connector {
16
- /** @type {import('express').Application} */
17
- #app
18
- /** @type {import('http').Server} */
19
- #server
20
-
21
- constructor () {
22
- super()
23
-
24
- // TODO: remove express
25
- this.#app = express()
26
- this.#app.disable('x-powered-by')
27
- this.#app.enable('case sensitive routing')
28
- this.#app.enable('strict routing')
29
- this.#app.disable('etag')
30
- this.#app.use(express.json())
31
- this.#app.use(cors({ allowedHeaders: ['content-type'] }))
32
-
33
- this.#app.use((req, res, next) => {
34
- req.safe = req.method in SAFE
35
-
36
- if (req.method in METHODS) next()
37
- else res.status(501).end()
38
- })
39
- }
40
-
41
- route (route, callback) {
42
- this.#app.use(route, callback)
43
- }
44
-
45
- async open () {
46
- console.info(`Starting HTTP server at :${PORT} ...`)
47
-
48
- return new Promise((resolve, reject) => {
49
- const error = () => reject(new Error(`Error starting HTTP server at :${PORT}`))
50
- // noinspection JSCheckFunctionSignatures
51
- this.#server = this.#app.listen(PORT, () => {
52
- console.info(`HTTP server at :${PORT} started`)
53
-
54
- this.#server.off('error', error)
55
- resolve()
56
- })
57
-
58
- this.#server.on('error', error)
59
- })
60
- }
61
-
62
- async close () {
63
- console.info(`Stopping HTTP server at :${PORT} ...`)
64
-
65
- return new Promise((resolve, reject) => {
66
- const error = () => reject(new Error(`Error stopping HTTP server at :${PORT}`))
67
-
68
- this.#server.close(() => {
69
- console.info(`HTTP server at :${PORT} stopped`)
70
-
71
- this.#server.off('error', error)
72
- resolve()
73
- })
74
-
75
- this.#server.on('error', error)
76
- })
77
- }
78
- }
79
-
80
- const METHODS = { HEAD: 1, GET: 1, POST: 1, PUT: 1, PATCH: 1 }
81
- const SAFE = { HEAD: 1, GET: 1 }
82
-
83
- exports.Server = Server
package/src/tenant.js DELETED
@@ -1,29 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
-
5
- class Tenant extends Connector {
6
- /** @type {toa.core.bindings.Broadcast} */
7
- #binding
8
- #declaration
9
-
10
- constructor (binding, { namespace, name }, resources) {
11
- super()
12
-
13
- this.#binding = binding
14
- this.#declaration = { namespace, name, resources }
15
-
16
- this.depends(binding)
17
- }
18
-
19
- async open () {
20
- await this.#binding.receive('ping', () => this.#expose())
21
- await this.#expose()
22
- }
23
-
24
- async #expose () {
25
- await this.#binding.transmit('expose', this.#declaration)
26
- }
27
- }
28
-
29
- exports.Tenant = Tenant
@@ -1,14 +0,0 @@
1
- 'use strict'
2
-
3
- const get = (header) => {
4
- const match = header.match(rx)
5
- return match === null ? null : match[1]
6
- }
7
-
8
- const set = (value) => '"' + value + '"'
9
-
10
- const rx = /^"([^"]+)"$/
11
-
12
- exports.get = get
13
- exports.set = set
14
- exports.rx = rx
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- const { request } = require('./request')
4
- const response = require('./response')
5
-
6
- exports.request = request
7
- exports.response = response
@@ -1,68 +0,0 @@
1
- 'use strict'
2
-
3
- const { exceptions: { RequestSyntaxException, RequestConflictException } } = require('@toa.io/core')
4
- const { empty } = require('@toa.io/generic')
5
-
6
- const etag = require('./etag')
7
-
8
- /**
9
- * @hot
10
- *
11
- * @param {import('express').Request} req
12
- * @param {{[key: string]: string}} params
13
- * @returns {toa.core.Request}
14
- */
15
- const request = (req, params) => {
16
- const request = {}
17
-
18
- if (!empty(req.body)) request.input = req.body
19
-
20
- if (!empty(req.query)) {
21
- request.query = req.query
22
-
23
- if (request.query.projection !== undefined) request.query.projection = request.query.projection.split(',')
24
- if (request.query.sort !== undefined) request.query.sort = request.query.sort.split(',')
25
- }
26
-
27
- if (!empty(params)) {
28
- if (req.method === 'POST') {
29
- if (request.input === undefined) request.input = {}
30
-
31
- for (const [key, value] of Object.entries(params)) {
32
- if (request.input[key] === undefined) request.input[key] = value
33
- else throw new RequestConflictException(`Input property '${key}' conflicts with path parameter`)
34
- }
35
- } else {
36
- const criteria = []
37
-
38
- if (request.query === undefined) request.query = {}
39
-
40
- for (const [key, value] of Object.entries(params)) {
41
- if (key === 'id') request.query.id = value
42
- else criteria.push(key + '==' + value)
43
- }
44
-
45
- if (criteria.length > 0) {
46
- const value = criteria.join(';')
47
-
48
- if (request.query.criteria === undefined) request.query.criteria = value
49
- else request.query.criteria = value + ';' + request.query.criteria
50
- }
51
- }
52
- }
53
-
54
- const condition = req.get('if-match')
55
-
56
- if (condition !== undefined && condition !== '*') {
57
- const value = etag.get(condition)
58
-
59
- if (value === null) throw new RequestSyntaxException('ETag value must match ' + etag.rx)
60
- if (request.query === undefined) request.query = {}
61
-
62
- request.query.version = +value
63
- }
64
-
65
- return request
66
- }
67
-
68
- exports.request = request
@@ -1,62 +0,0 @@
1
- 'use strict'
2
-
3
- const { exceptions: { codes } } = require('@toa.io/core')
4
-
5
- const etag = require('./etag')
6
-
7
- /**
8
- * @param {toa.core.Reply} reply
9
- * @param res
10
- * @param req
11
- * @hot
12
- */
13
- const ok = (reply, res, req) => {
14
- if (reply.output?._version !== undefined) {
15
- const { _version, ...output } = reply.output
16
- const condition = req.get('if-none-match')
17
-
18
- if (condition !== undefined && req.safe) {
19
- const value = etag.get(condition)
20
-
21
- if (value === _version) {
22
- res.status(304).end()
23
- return
24
- }
25
- }
26
-
27
- res.set('etag', etag.set(_version))
28
- reply.output = output
29
- }
30
-
31
- let status
32
-
33
- if (req.method === 'POST') status = 201
34
- else if (reply.output !== undefined || reply.error !== undefined) status = 200
35
- else status = 204
36
-
37
- res.status(status)
38
- if (status !== 204) res.send(reply)
39
- }
40
-
41
- const missed = (response) => response.status(404)
42
-
43
- const exception = (exception, response) => {
44
- const status = STATUSES[exception.code] || 500
45
-
46
- response.status(status)
47
- response.send(exception)
48
- }
49
-
50
- const STATUSES = {
51
- [codes.RequestContract]: 400,
52
- [codes.RequestSyntax]: 400,
53
- [codes.QuerySyntax]: 400,
54
- [codes.RequestConflict]: 403,
55
- [codes.StateNotFound]: 404,
56
- [codes.NotImplemented]: 405,
57
- [codes.StatePrecondition]: 412
58
- }
59
-
60
- exports.ok = ok
61
- exports.missed = missed
62
- exports.exception = exception
package/src/tree.js DELETED
@@ -1,109 +0,0 @@
1
- 'use strict'
2
-
3
- const path = require('path')
4
- const { match } = require('path-to-regexp')
5
-
6
- const { console } = require('@toa.io/console')
7
-
8
- /**
9
- * @implements {toa.extensions.exposition.Tree}
10
- */
11
- class Tree {
12
- /** @type {toa.extensions.exposition.tree.Node[]} */
13
- #nodes
14
-
15
- /** @type {toa.extensions.exposition.query.Factory} */
16
- #query
17
-
18
- /**
19
- * @param {toa.extensions.exposition.query.Factory} query
20
- */
21
- constructor (query) {
22
- this.#query = query
23
- }
24
-
25
- /** @hot */
26
- match (path) {
27
- // dev only check
28
- if (process.env.TOA_ENV === 'local') {
29
- const nodes = this.#nodes.filter((node) => node.match(path) !== false)
30
-
31
- if (nodes.length > 1) {
32
- const routes = nodes.map((node) => node.route)
33
-
34
- throw new Error('Ambiguous routes ' + routes.join(', '))
35
- }
36
- }
37
-
38
- let match
39
-
40
- const node = this.#nodes.find((node) => {
41
- match = node.match(path)
42
- return match !== false
43
- })
44
-
45
- return node === undefined ? undefined : { node, params: match.params }
46
- }
47
-
48
- update (tree) {
49
- this.#nodes = []
50
- this.#traverse(tree)
51
- }
52
-
53
- /**
54
- * @param {toa.extensions.exposition.declarations.Node | any} node
55
- * @param {string} route
56
- * @param {toa.extensions.exposition.declarations.Node} parent
57
- */
58
- #traverse (node, route = undefined, parent = undefined) {
59
- const current = {}
60
-
61
- if (route === undefined) route = '/'
62
- else route = trail(route)
63
-
64
- if (parent !== undefined) node.parent = parent
65
-
66
- if (node.operations) {
67
- current.route = route
68
- current.match = match(route)
69
- current.query = this.#query(node)
70
- current.operations = {}
71
-
72
- for (const operation of node.operations) current.operations[method(operation)] = operation
73
-
74
- this.#nodes.push(current)
75
- }
76
-
77
- let branches = 0
78
-
79
- for (const [key, value] of Object.entries(node)) {
80
- if (key[0] === '/') {
81
- branches++
82
-
83
- const branch = path.posix.resolve(route, '.' + key)
84
-
85
- this.#traverse(value, branch, node)
86
- }
87
- }
88
-
89
- if (branches === 0 && node.operations === undefined) {
90
- console.warn(`Resource tree leaf '${route}' has no operations`)
91
- }
92
- }
93
- }
94
-
95
- const trail = (path) => path[path.length - 1] === '/' ? path : path + '/'
96
-
97
- const method = (operation) => {
98
- if (operation.type === 'transition') {
99
- if (operation.query === false) return 'POST'
100
- else return 'PUT'
101
- }
102
-
103
- if (operation.type === 'observation') return 'GET'
104
- if (operation.type === 'assignment') return 'PATCH'
105
- if (operation.type === 'computation') return 'GET'
106
- if (operation.type === 'effect') return 'POST'
107
- }
108
-
109
- exports.Tree = Tree
@@ -1,37 +0,0 @@
1
- 'use strict'
2
-
3
- const manifest = {
4
- operations: {
5
- one: {
6
- type: 'transition',
7
- scope: 'object',
8
- query: false
9
- },
10
- two: {
11
- type: 'observation',
12
- scope: 'objects'
13
- },
14
- three: {
15
- type: 'observation',
16
- scope: 'objects'
17
- }
18
- }
19
- }
20
-
21
- const resources = {
22
- '/': ['one', 'two'],
23
- '/top': {
24
- operations: ['one'],
25
- '/nested': {
26
- operations: ['two'],
27
- '/deeper': {
28
- operations: [{
29
- operation: 'three'
30
- }]
31
- }
32
- }
33
- }
34
- }
35
-
36
- exports.manifest = manifest
37
- exports.resources = resources
@@ -1,37 +0,0 @@
1
- 'use strict'
2
-
3
- const clone = require('clone-deep')
4
-
5
- const { normalize } = require('../src/.manifest')
6
- const fixtures = require('./manifest.normalize.fixtures')
7
-
8
- describe('normalize', () => {
9
- let manifest, resources
10
-
11
- const map = (operation) => ({
12
- ...fixtures.manifest.operations[operation],
13
- operation
14
- })
15
-
16
- beforeEach(() => {
17
- manifest = clone(fixtures.manifest)
18
- resources = clone(fixtures.resources)
19
- })
20
-
21
- it('should expand array', () => {
22
- normalize(resources, manifest)
23
-
24
- expect(resources['/'].operations)
25
- .toStrictEqual(fixtures.resources['/'].map(map))
26
- })
27
-
28
- it('should expand operations', () => {
29
- normalize(resources, manifest)
30
-
31
- expect(resources['/top'].operations)
32
- .toStrictEqual(fixtures.resources['/top'].operations.map(map))
33
-
34
- expect(resources['/top']['/nested'].operations)
35
- .toStrictEqual(fixtures.resources['/top']['/nested'].operations.map(map))
36
- })
37
- })
@@ -1,40 +0,0 @@
1
- 'use strict'
2
-
3
- const { validate } = require('../src/.manifest')
4
-
5
- it('should validate', () => {
6
- const resources = {
7
- '/path/to': {
8
- operations: [
9
- {
10
- operation: 'foo',
11
- type: 'observation'
12
- }
13
- ],
14
- '/deeper/': {
15
- operations: [{
16
- operation: 'bar',
17
- type: 'transition',
18
- query: false
19
- }]
20
- }
21
- }
22
- }
23
-
24
- expect(() => validate(resources)).not.toThrow()
25
- })
26
-
27
- it.each(['computation', 'effect'])('should allow %s operation', async (type) => {
28
- const resources = {
29
- '/path/to': {
30
- operations: [
31
- {
32
- operation: 'foo',
33
- type
34
- }
35
- ]
36
- }
37
- }
38
-
39
- expect(() => validate(resources)).not.toThrow()
40
- })