@toa.io/extensions.exposition 1.0.0-alpha.9 → 1.0.0-alpha.91

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 (489) hide show
  1. package/components/context.toa.yaml +2 -2
  2. package/components/identity.bans/manifest.toa.yaml +14 -6
  3. package/components/identity.bans/operations/transit.d.ts +14 -0
  4. package/components/identity.bans/operations/transit.js +11 -0
  5. package/components/identity.bans/operations/transit.js.map +1 -0
  6. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
  7. package/components/identity.bans/source/transit.ts +21 -0
  8. package/components/identity.bans/tsconfig.json +9 -0
  9. package/components/identity.basic/manifest.toa.yaml +20 -10
  10. package/components/identity.basic/operations/authenticate.d.ts +5 -1
  11. package/components/identity.basic/operations/authenticate.js +5 -2
  12. package/components/identity.basic/operations/authenticate.js.map +1 -1
  13. package/components/identity.basic/operations/incept.d.ts +12 -0
  14. package/components/identity.basic/operations/incept.js +26 -0
  15. package/components/identity.basic/operations/incept.js.map +1 -0
  16. package/components/identity.basic/operations/transit.d.ts +4 -4
  17. package/components/identity.basic/operations/transit.js +8 -6
  18. package/components/identity.basic/operations/transit.js.map +1 -1
  19. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  20. package/components/identity.basic/operations/types.d.ts +8 -4
  21. package/components/identity.basic/source/authenticate.ts +16 -5
  22. package/components/identity.basic/source/incept.ts +38 -0
  23. package/components/identity.basic/source/transit.ts +11 -9
  24. package/components/identity.basic/source/types.ts +8 -4
  25. package/components/identity.federation/manifest.toa.yaml +32 -15
  26. package/components/identity.federation/operations/authenticate.d.ts +2 -2
  27. package/components/identity.federation/operations/authenticate.js +4 -11
  28. package/components/identity.federation/operations/authenticate.js.map +1 -1
  29. package/components/identity.federation/operations/incept.d.ts +11 -0
  30. package/components/identity.federation/operations/{create.js → incept.js} +6 -7
  31. package/components/identity.federation/operations/incept.js.map +1 -0
  32. package/components/identity.federation/operations/lib/assertions-as-values.js +4 -2
  33. package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -1
  34. package/components/identity.federation/operations/lib/jwt.d.ts +5 -5
  35. package/components/identity.federation/operations/lib/jwt.js +25 -12
  36. package/components/identity.federation/operations/lib/jwt.js.map +1 -1
  37. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  38. package/components/identity.federation/operations/types/configuration.d.ts +14 -0
  39. package/components/identity.federation/operations/types/configuration.js +3 -0
  40. package/components/identity.federation/operations/types/configuration.js.map +1 -0
  41. package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +15 -7
  42. package/components/identity.federation/operations/types/context.js +3 -0
  43. package/components/identity.federation/operations/types/context.js.map +1 -0
  44. package/components/identity.federation/operations/types/entity.d.ts +6 -0
  45. package/components/identity.federation/operations/types/entity.js +3 -0
  46. package/components/identity.federation/operations/types/entity.js.map +1 -0
  47. package/components/identity.federation/operations/types/index.d.ts +3 -0
  48. package/components/identity.federation/operations/types/index.js +20 -0
  49. package/components/identity.federation/operations/types/index.js.map +1 -0
  50. package/components/identity.federation/source/authenticate.ts +6 -19
  51. package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
  52. package/components/identity.federation/source/lib/assertions-as-values.ts +5 -2
  53. package/components/identity.federation/source/lib/jwt.test.ts +123 -4
  54. package/components/identity.federation/source/lib/jwt.ts +36 -16
  55. package/components/identity.federation/source/types/configuration.ts +15 -0
  56. package/components/identity.federation/source/{types.ts → types/context.ts} +17 -6
  57. package/components/identity.federation/source/types/entity.ts +6 -0
  58. package/components/identity.federation/source/types/index.ts +3 -0
  59. package/components/identity.federation/tsconfig.json +5 -4
  60. package/components/identity.roles/manifest.toa.yaml +16 -6
  61. package/components/identity.roles/operations/grant.d.ts +10 -0
  62. package/components/identity.roles/operations/grant.js +21 -0
  63. package/components/identity.roles/operations/grant.js.map +1 -0
  64. package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
  65. package/components/identity.roles/operations/lib/Entity.js +3 -0
  66. package/components/identity.roles/operations/lib/Entity.js.map +1 -0
  67. package/components/identity.roles/operations/list.d.ts +1 -4
  68. package/components/identity.roles/operations/list.js.map +1 -1
  69. package/components/identity.roles/operations/principal.d.ts +4 -6
  70. package/components/identity.roles/operations/principal.js +6 -1
  71. package/components/identity.roles/operations/principal.js.map +1 -1
  72. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  73. package/components/identity.roles/source/grant.ts +32 -0
  74. package/components/identity.roles/source/lib/Entity.ts +5 -0
  75. package/components/identity.roles/source/list.ts +2 -4
  76. package/components/identity.roles/source/principal.ts +10 -8
  77. package/components/identity.tokens/manifest.toa.yaml +19 -4
  78. package/components/identity.tokens/operations/authenticate.d.ts +2 -2
  79. package/components/identity.tokens/operations/authenticate.js +12 -5
  80. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  81. package/components/identity.tokens/operations/decrypt.js +1 -0
  82. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  83. package/components/identity.tokens/operations/encrypt.js +5 -1
  84. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  85. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  86. package/components/identity.tokens/operations/types.d.ts +8 -2
  87. package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
  88. package/components/identity.tokens/source/authenticate.test.ts +11 -4
  89. package/components/identity.tokens/source/authenticate.ts +14 -6
  90. package/components/identity.tokens/source/decrypt.test.ts +5 -3
  91. package/components/identity.tokens/source/decrypt.ts +9 -8
  92. package/components/identity.tokens/source/encrypt.test.ts +26 -2
  93. package/components/identity.tokens/source/encrypt.ts +5 -1
  94. package/components/identity.tokens/source/types.ts +9 -2
  95. package/components/octets.storage/manifest.toa.yaml +9 -11
  96. package/components/octets.storage/operations/get.js +3 -3
  97. package/components/octets.storage/operations/head.js +7 -0
  98. package/components/octets.storage/operations/put.js +121 -0
  99. package/documentation/access.md +75 -38
  100. package/documentation/authorities.md +49 -0
  101. package/documentation/cache.md +8 -1
  102. package/documentation/components.md +61 -22
  103. package/documentation/flow.md +44 -0
  104. package/documentation/identity.md +17 -22
  105. package/documentation/introspection.md +82 -0
  106. package/documentation/octets.md +95 -67
  107. package/documentation/protocol.md +13 -3
  108. package/documentation/query.md +29 -4
  109. package/documentation/require.md +15 -0
  110. package/documentation/tree.md +13 -0
  111. package/documentation/vary.md +14 -14
  112. package/features/access.feature +77 -46
  113. package/features/annotation.feature +1 -0
  114. package/features/auth.claim.feature +170 -0
  115. package/features/authorities.basic.feature +141 -0
  116. package/features/authorities.feature +32 -0
  117. package/features/authorities.federation.feature +100 -0
  118. package/features/authorities.tokens.feature +117 -0
  119. package/features/body.feature +2 -0
  120. package/features/cache.feature +109 -5
  121. package/features/cors.feature +6 -1
  122. package/features/debug.feature +34 -0
  123. package/features/directives.feature +3 -0
  124. package/features/dynamic.feature +48 -0
  125. package/features/errors.feature +32 -7
  126. package/features/etag.feature +108 -0
  127. package/features/flow.feature +96 -0
  128. package/features/identity.bans.feature +137 -0
  129. package/features/identity.basic.feature +97 -26
  130. package/features/identity.feature +18 -6
  131. package/features/identity.federation.feature +66 -11
  132. package/features/identity.roles.feature +250 -7
  133. package/features/identity.tokens.feature +54 -4
  134. package/features/introspection.feature +153 -0
  135. package/features/io.feature +38 -1
  136. package/features/methods.feature +47 -0
  137. package/features/{octets.meta.feature → octets.attributes.feature} +16 -12
  138. package/features/octets.cloudinary.feature +68 -0
  139. package/features/octets.download.feature +189 -0
  140. package/features/octets.entries.feature +13 -55
  141. package/features/octets.feature +83 -107
  142. package/features/octets.workflows.feature +242 -58
  143. package/features/probes.feature +14 -0
  144. package/features/{queries.feature → query.feature} +77 -2
  145. package/features/realtime.feature +34 -0
  146. package/features/require.feature +67 -0
  147. package/features/response.feature +38 -3
  148. package/features/routes.feature +93 -2
  149. package/features/server.feature +21 -0
  150. package/features/steps/.env.example +3 -0
  151. package/features/steps/Database.ts +16 -9
  152. package/features/steps/Gateway.ts +23 -6
  153. package/features/steps/IdP.ts +30 -25
  154. package/features/steps/Parameters.ts +44 -1
  155. package/features/steps/Realtime.ts +151 -0
  156. package/features/steps/components/echo/manifest.toa.yaml +14 -1
  157. package/features/steps/components/echo/operations/identity.js +7 -0
  158. package/features/steps/components/echo/operations/parameters.js +7 -0
  159. package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
  160. package/features/steps/components/echo.beacon/operations/hello.js +5 -0
  161. package/features/steps/components/octets.tester/manifest.toa.yaml +22 -2
  162. package/features/steps/components/octets.tester/operations/authority.js +7 -0
  163. package/features/steps/components/octets.tester/operations/bar.js +0 -1
  164. package/features/steps/components/octets.tester/operations/baz.js +0 -2
  165. package/features/steps/components/octets.tester/operations/foo.js +1 -2
  166. package/features/steps/components/octets.tester/operations/redirect.js +12 -0
  167. package/features/steps/components/octets.tester/operations/yex.js +16 -0
  168. package/features/steps/components/octets.tester/operations/yield.js +13 -0
  169. package/features/steps/components/pots/manifest.toa.yaml +14 -3
  170. package/features/steps/components/users/manifest.toa.yaml +0 -1
  171. package/features/steps/components/users.properties/manifest.toa.yaml +1 -1
  172. package/features/streams.feature +5 -0
  173. package/features/timing.feature +4 -1
  174. package/features/vary.feature +71 -0
  175. package/package.json +23 -14
  176. package/readme.md +19 -14
  177. package/schemas/annotation.cos.yaml +1 -1
  178. package/schemas/method.cos.yaml +1 -1
  179. package/schemas/node.cos.yaml +2 -0
  180. package/schemas/octets/put.cos.yaml +25 -0
  181. package/schemas/query.cos.yaml +4 -10
  182. package/source/Annotation.ts +3 -3
  183. package/source/Branch.ts +1 -0
  184. package/source/Composition.ts +0 -6
  185. package/source/Context.ts +1 -0
  186. package/source/Directive.test.ts +1 -1
  187. package/source/Directive.ts +5 -6
  188. package/source/Endpoint.ts +59 -17
  189. package/source/Factory.ts +22 -13
  190. package/source/Gateway.ts +65 -18
  191. package/source/HTTP/Context.ts +26 -3
  192. package/source/HTTP/Server.ts +60 -46
  193. package/source/HTTP/exceptions.ts +13 -1
  194. package/source/HTTP/formats/index.ts +3 -3
  195. package/source/HTTP/messages.test.ts +45 -2
  196. package/source/HTTP/messages.ts +32 -8
  197. package/source/Introspection.ts +11 -0
  198. package/source/Mapping.ts +68 -21
  199. package/source/Query.test.ts +3 -3
  200. package/source/Query.ts +123 -33
  201. package/source/RTD/Context.ts +1 -1
  202. package/source/RTD/Endpoint.ts +3 -0
  203. package/source/RTD/Method.ts +16 -0
  204. package/source/RTD/Node.ts +29 -13
  205. package/source/RTD/Route.ts +5 -4
  206. package/source/RTD/Tree.ts +2 -2
  207. package/source/RTD/factory.ts +5 -2
  208. package/source/RTD/syntax/parse.test.ts +1 -1
  209. package/source/RTD/syntax/parse.ts +37 -24
  210. package/source/RTD/syntax/types.ts +6 -4
  211. package/source/Remotes.ts +7 -6
  212. package/source/Tenant.ts +6 -20
  213. package/source/deployment.ts +33 -23
  214. package/source/directives/auth/Authorization.ts +45 -22
  215. package/source/directives/auth/Delegate.ts +42 -0
  216. package/source/directives/auth/Echo.ts +19 -5
  217. package/source/directives/auth/Federation.ts +84 -0
  218. package/source/directives/auth/Incept.ts +4 -3
  219. package/source/directives/auth/Role.test.ts +53 -6
  220. package/source/directives/auth/Role.ts +22 -14
  221. package/source/directives/auth/Scheme.ts +1 -1
  222. package/source/directives/auth/split.ts +1 -1
  223. package/source/directives/auth/types.ts +2 -2
  224. package/source/directives/cache/Cache.ts +13 -6
  225. package/source/directives/cache/Control.ts +42 -16
  226. package/source/directives/cors/CORS.ts +1 -1
  227. package/source/directives/dev/Development.ts +1 -1
  228. package/source/directives/flow/Compose.ts +68 -0
  229. package/source/directives/flow/Fetch.ts +86 -0
  230. package/source/directives/flow/Flow.ts +42 -0
  231. package/source/directives/flow/index.ts +3 -0
  232. package/source/directives/flow/types.ts +7 -0
  233. package/source/directives/index.ts +3 -1
  234. package/source/directives/io/IO.ts +1 -1
  235. package/source/directives/io/Input.ts +4 -4
  236. package/source/directives/io/Output.ts +5 -4
  237. package/source/directives/octets/Context.ts +3 -2
  238. package/source/directives/octets/Delete.ts +11 -11
  239. package/source/directives/octets/Get.ts +84 -0
  240. package/source/directives/octets/Octets.ts +8 -12
  241. package/source/directives/octets/{Store.ts → Put.ts} +36 -21
  242. package/source/directives/octets/Workflow.ts +1 -1
  243. package/source/directives/octets/bytes.test.ts +30 -0
  244. package/source/directives/octets/bytes.ts +18 -0
  245. package/source/directives/octets/schemas.ts +4 -8
  246. package/source/directives/octets/workflows/Execution.ts +60 -8
  247. package/source/directives/octets/workflows/Workflow.ts +4 -4
  248. package/source/directives/require/Directive.ts +5 -0
  249. package/source/directives/require/Headers.ts +20 -0
  250. package/source/directives/require/Require.ts +28 -0
  251. package/source/directives/require/index.ts +3 -0
  252. package/source/directives/vary/Directive.ts +2 -1
  253. package/source/directives/vary/Embed.ts +14 -8
  254. package/source/directives/vary/Vary.ts +6 -4
  255. package/source/directives/vary/embeddings/Authority.ts +8 -0
  256. package/source/directives/vary/embeddings/Embedding.ts +2 -1
  257. package/source/directives/vary/embeddings/Language.ts +2 -2
  258. package/source/directives/vary/embeddings/Parameter.ts +14 -0
  259. package/source/directives/vary/embeddings/index.ts +6 -4
  260. package/source/exceptions.ts +17 -11
  261. package/source/manifest.ts +10 -11
  262. package/source/root.ts +5 -5
  263. package/source/schemas.ts +1 -1
  264. package/transpiled/Annotation.d.ts +3 -3
  265. package/transpiled/Branch.d.ts +1 -0
  266. package/transpiled/Composition.d.ts +0 -1
  267. package/transpiled/Composition.js +0 -4
  268. package/transpiled/Composition.js.map +1 -1
  269. package/transpiled/Context.d.ts +1 -0
  270. package/transpiled/Directive.js +5 -5
  271. package/transpiled/Directive.js.map +1 -1
  272. package/transpiled/Endpoint.d.ts +6 -4
  273. package/transpiled/Endpoint.js +39 -9
  274. package/transpiled/Endpoint.js.map +1 -1
  275. package/transpiled/Factory.d.ts +3 -2
  276. package/transpiled/Factory.js +18 -10
  277. package/transpiled/Factory.js.map +1 -1
  278. package/transpiled/Gateway.d.ts +3 -0
  279. package/transpiled/Gateway.js +49 -10
  280. package/transpiled/Gateway.js.map +1 -1
  281. package/transpiled/HTTP/Context.d.ts +9 -2
  282. package/transpiled/HTTP/Context.js +16 -2
  283. package/transpiled/HTTP/Context.js.map +1 -1
  284. package/transpiled/HTTP/Server.d.ts +13 -2
  285. package/transpiled/HTTP/Server.js +46 -39
  286. package/transpiled/HTTP/Server.js.map +1 -1
  287. package/transpiled/HTTP/exceptions.d.ts +7 -1
  288. package/transpiled/HTTP/exceptions.js +13 -1
  289. package/transpiled/HTTP/exceptions.js.map +1 -1
  290. package/transpiled/HTTP/formats/index.js +3 -3
  291. package/transpiled/HTTP/formats/index.js.map +1 -1
  292. package/transpiled/HTTP/messages.d.ts +2 -1
  293. package/transpiled/HTTP/messages.js +30 -7
  294. package/transpiled/HTTP/messages.js.map +1 -1
  295. package/transpiled/Introspection.d.ts +9 -0
  296. package/transpiled/Introspection.js +3 -0
  297. package/transpiled/Introspection.js.map +1 -0
  298. package/transpiled/Mapping.d.ts +11 -2
  299. package/transpiled/Mapping.js +50 -19
  300. package/transpiled/Mapping.js.map +1 -1
  301. package/transpiled/Query.d.ts +10 -1
  302. package/transpiled/Query.js +87 -30
  303. package/transpiled/Query.js.map +1 -1
  304. package/transpiled/RTD/Context.d.ts +1 -1
  305. package/transpiled/RTD/Endpoint.d.ts +1 -0
  306. package/transpiled/RTD/Method.d.ts +4 -0
  307. package/transpiled/RTD/Method.js +11 -0
  308. package/transpiled/RTD/Method.js.map +1 -1
  309. package/transpiled/RTD/Node.d.ts +4 -1
  310. package/transpiled/RTD/Node.js +23 -12
  311. package/transpiled/RTD/Node.js.map +1 -1
  312. package/transpiled/RTD/Route.d.ts +1 -1
  313. package/transpiled/RTD/Route.js +0 -1
  314. package/transpiled/RTD/Route.js.map +1 -1
  315. package/transpiled/RTD/Tree.d.ts +1 -1
  316. package/transpiled/RTD/Tree.js.map +1 -1
  317. package/transpiled/RTD/factory.js +5 -2
  318. package/transpiled/RTD/factory.js.map +1 -1
  319. package/transpiled/RTD/syntax/parse.js +34 -22
  320. package/transpiled/RTD/syntax/parse.js.map +1 -1
  321. package/transpiled/RTD/syntax/types.d.ts +5 -3
  322. package/transpiled/RTD/syntax/types.js +1 -1
  323. package/transpiled/RTD/syntax/types.js.map +1 -1
  324. package/transpiled/Remotes.d.ts +4 -4
  325. package/transpiled/Remotes.js +6 -5
  326. package/transpiled/Remotes.js.map +1 -1
  327. package/transpiled/Tenant.d.ts +5 -5
  328. package/transpiled/Tenant.js +2 -13
  329. package/transpiled/Tenant.js.map +1 -1
  330. package/transpiled/deployment.d.ts +1 -1
  331. package/transpiled/deployment.js +28 -20
  332. package/transpiled/deployment.js.map +1 -1
  333. package/transpiled/directives/auth/Authorization.d.ts +1 -1
  334. package/transpiled/directives/auth/Authorization.js +33 -19
  335. package/transpiled/directives/auth/Authorization.js.map +1 -1
  336. package/transpiled/directives/auth/Delegate.d.ts +10 -0
  337. package/transpiled/directives/auth/Delegate.js +34 -0
  338. package/transpiled/directives/auth/Delegate.js.map +1 -0
  339. package/transpiled/directives/auth/Echo.d.ts +4 -3
  340. package/transpiled/directives/auth/Echo.js +13 -3
  341. package/transpiled/directives/auth/Echo.js.map +1 -1
  342. package/transpiled/directives/auth/Federation.d.ts +16 -0
  343. package/transpiled/directives/auth/Federation.js +57 -0
  344. package/transpiled/directives/auth/Federation.js.map +1 -0
  345. package/transpiled/directives/auth/Incept.js +4 -3
  346. package/transpiled/directives/auth/Incept.js.map +1 -1
  347. package/transpiled/directives/auth/Role.d.ts +4 -1
  348. package/transpiled/directives/auth/Role.js +20 -14
  349. package/transpiled/directives/auth/Role.js.map +1 -1
  350. package/transpiled/directives/auth/Scheme.js +1 -1
  351. package/transpiled/directives/auth/Scheme.js.map +1 -1
  352. package/transpiled/directives/auth/split.js +1 -1
  353. package/transpiled/directives/auth/split.js.map +1 -1
  354. package/transpiled/directives/auth/types.d.ts +1 -1
  355. package/transpiled/directives/cache/Cache.d.ts +3 -3
  356. package/transpiled/directives/cache/Cache.js +10 -4
  357. package/transpiled/directives/cache/Cache.js.map +1 -1
  358. package/transpiled/directives/cache/Control.d.ts +2 -1
  359. package/transpiled/directives/cache/Control.js +29 -12
  360. package/transpiled/directives/cache/Control.js.map +1 -1
  361. package/transpiled/directives/cors/CORS.js +1 -1
  362. package/transpiled/directives/cors/CORS.js.map +1 -1
  363. package/transpiled/directives/dev/Development.js +1 -1
  364. package/transpiled/directives/dev/Development.js.map +1 -1
  365. package/transpiled/directives/flow/Compose.d.ts +8 -0
  366. package/transpiled/directives/flow/Compose.js +74 -0
  367. package/transpiled/directives/flow/Compose.js.map +1 -0
  368. package/transpiled/directives/flow/Fetch.d.ts +12 -0
  369. package/transpiled/directives/flow/Fetch.js +58 -0
  370. package/transpiled/directives/flow/Fetch.js.map +1 -0
  371. package/transpiled/directives/flow/Flow.d.ts +10 -0
  372. package/transpiled/directives/flow/Flow.js +33 -0
  373. package/transpiled/directives/flow/Flow.js.map +1 -0
  374. package/transpiled/directives/flow/index.d.ts +2 -0
  375. package/transpiled/directives/flow/index.js +6 -0
  376. package/transpiled/directives/flow/index.js.map +1 -0
  377. package/transpiled/directives/flow/types.d.ts +6 -0
  378. package/transpiled/directives/flow/types.js.map +1 -0
  379. package/transpiled/directives/index.js +3 -1
  380. package/transpiled/directives/index.js.map +1 -1
  381. package/transpiled/directives/io/IO.js +1 -1
  382. package/transpiled/directives/io/IO.js.map +1 -1
  383. package/transpiled/directives/io/Input.js +2 -2
  384. package/transpiled/directives/io/Input.js.map +1 -1
  385. package/transpiled/directives/io/Output.js +2 -2
  386. package/transpiled/directives/io/Output.js.map +1 -1
  387. package/transpiled/directives/octets/Context.js +4 -24
  388. package/transpiled/directives/octets/Context.js.map +1 -1
  389. package/transpiled/directives/octets/Delete.js +8 -8
  390. package/transpiled/directives/octets/Delete.js.map +1 -1
  391. package/transpiled/directives/octets/{Fetch.d.ts → Get.d.ts} +5 -6
  392. package/transpiled/directives/octets/{Fetch.js → Get.js} +24 -29
  393. package/transpiled/directives/octets/Get.js.map +1 -0
  394. package/transpiled/directives/octets/Octets.js +8 -12
  395. package/transpiled/directives/octets/Octets.js.map +1 -1
  396. package/transpiled/directives/octets/{Store.d.ts → Put.d.ts} +7 -2
  397. package/transpiled/directives/octets/{Store.js → Put.js} +26 -19
  398. package/transpiled/directives/octets/Put.js.map +1 -0
  399. package/transpiled/directives/octets/Workflow.js +1 -1
  400. package/transpiled/directives/octets/Workflow.js.map +1 -1
  401. package/transpiled/directives/octets/bytes.d.ts +1 -0
  402. package/transpiled/directives/octets/bytes.js +21 -0
  403. package/transpiled/directives/octets/bytes.js.map +1 -0
  404. package/transpiled/directives/octets/schemas.d.ts +4 -8
  405. package/transpiled/directives/octets/schemas.js +3 -6
  406. package/transpiled/directives/octets/schemas.js.map +1 -1
  407. package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
  408. package/transpiled/directives/octets/workflows/Execution.js +44 -9
  409. package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
  410. package/transpiled/directives/octets/workflows/Workflow.d.ts +1 -1
  411. package/transpiled/directives/octets/workflows/Workflow.js +2 -1
  412. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  413. package/transpiled/directives/require/Directive.d.ts +4 -0
  414. package/transpiled/directives/require/Directive.js +3 -0
  415. package/transpiled/directives/require/Directive.js.map +1 -0
  416. package/transpiled/directives/require/Headers.d.ts +7 -0
  417. package/transpiled/directives/require/Headers.js +19 -0
  418. package/transpiled/directives/require/Headers.js.map +1 -0
  419. package/transpiled/directives/require/Require.d.ts +9 -0
  420. package/transpiled/directives/require/Require.js +27 -0
  421. package/transpiled/directives/require/Require.js.map +1 -0
  422. package/transpiled/directives/require/index.d.ts +2 -0
  423. package/transpiled/directives/require/index.js +6 -0
  424. package/transpiled/directives/require/index.js.map +1 -0
  425. package/transpiled/directives/vary/Directive.d.ts +2 -1
  426. package/transpiled/directives/vary/Embed.d.ts +2 -1
  427. package/transpiled/directives/vary/Embed.js +8 -6
  428. package/transpiled/directives/vary/Embed.js.map +1 -1
  429. package/transpiled/directives/vary/Vary.d.ts +2 -2
  430. package/transpiled/directives/vary/Vary.js +3 -3
  431. package/transpiled/directives/vary/Vary.js.map +1 -1
  432. package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
  433. package/transpiled/directives/vary/embeddings/Authority.js +10 -0
  434. package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
  435. package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
  436. package/transpiled/directives/vary/embeddings/Language.js +2 -2
  437. package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
  438. package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
  439. package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
  440. package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
  441. package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
  442. package/transpiled/directives/vary/embeddings/index.js +8 -4
  443. package/transpiled/directives/vary/embeddings/index.js.map +1 -1
  444. package/transpiled/exceptions.d.ts +3 -2
  445. package/transpiled/exceptions.js +10 -5
  446. package/transpiled/exceptions.js.map +1 -1
  447. package/transpiled/manifest.js +10 -11
  448. package/transpiled/manifest.js.map +1 -1
  449. package/transpiled/root.js +5 -5
  450. package/transpiled/root.js.map +1 -1
  451. package/transpiled/schemas.d.ts +1 -1
  452. package/transpiled/schemas.js +2 -2
  453. package/transpiled/schemas.js.map +1 -1
  454. package/transpiled/tsconfig.tsbuildinfo +1 -1
  455. package/tsconfig.json +8 -2
  456. package/components/identity.basic/operations/create.d.ts +0 -10
  457. package/components/identity.basic/operations/create.js +0 -10
  458. package/components/identity.basic/operations/create.js.map +0 -1
  459. package/components/identity.basic/source/create.ts +0 -18
  460. package/components/identity.federation/operations/create.d.ts +0 -10
  461. package/components/identity.federation/operations/create.js.map +0 -1
  462. package/components/identity.federation/operations/schemas.d.ts +0 -59
  463. package/components/identity.federation/operations/schemas.js +0 -9
  464. package/components/identity.federation/operations/schemas.js.map +0 -1
  465. package/components/identity.federation/operations/types.js.map +0 -1
  466. package/components/identity.federation/source/schemas.ts +0 -61
  467. package/components/octets.storage/operations/fetch.js +0 -46
  468. package/components/octets.storage/operations/list.js +0 -7
  469. package/components/octets.storage/operations/permute.js +0 -7
  470. package/components/octets.storage/operations/store.js +0 -11
  471. package/features/steps/components/octets.tester/operations/diversify.js +0 -14
  472. package/schemas/octets/context.cos.yaml +0 -1
  473. package/schemas/octets/fetch.cos.yaml +0 -3
  474. package/schemas/octets/permute.cos.yaml +0 -1
  475. package/schemas/octets/store.cos.yaml +0 -3
  476. package/source/HTTP/Server.test.ts +0 -126
  477. package/source/directives/octets/Fetch.ts +0 -100
  478. package/source/directives/octets/List.ts +0 -72
  479. package/source/directives/octets/Permute.ts +0 -44
  480. package/transpiled/directives/octets/Fetch.js.map +0 -1
  481. package/transpiled/directives/octets/List.d.ts +0 -16
  482. package/transpiled/directives/octets/List.js +0 -74
  483. package/transpiled/directives/octets/List.js.map +0 -1
  484. package/transpiled/directives/octets/Permute.d.ts +0 -11
  485. package/transpiled/directives/octets/Permute.js +0 -58
  486. package/transpiled/directives/octets/Permute.js.map +0 -1
  487. package/transpiled/directives/octets/Store.js.map +0 -1
  488. /package/schemas/octets/{list.cos.yaml → get.cos.yaml} +0 -0
  489. /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
package/readme.md CHANGED
@@ -20,7 +20,8 @@ exposition:
20
20
  # context.toa.yaml
21
21
 
22
22
  exposition:
23
- host: api.example.com
23
+ authorities:
24
+ example: api.example.com
24
25
  ```
25
26
 
26
27
  ```http
@@ -117,33 +118,36 @@ The Exposition annotation declares options for its deployment.
117
118
  ```yaml
118
119
  annotations:
119
120
  '@toa.io/extensions.exposition':
120
- host: the.exmaple.com
121
+ authorities:
122
+ example: the.example.com
121
123
  ```
122
124
 
123
125
  A shortcut is also available.
124
126
 
125
127
  ```yaml
126
128
  exposition:
127
- host: the.example.com
129
+ authorities:
130
+ example: the.example.com
128
131
  ```
129
132
 
130
- | Option | Type | Description |
131
- |---------------|-----------|-------------------------------------------------------------------------------------------------------------------|
132
- | `host` | `string` | Domain name to be used for the corresponding Kubernetes Ingress. |
133
- | `class` | `string` | Ingress class |
134
- | `annotations` | `object` | Ingress annotations |
135
- | `debug` | `boolean` | Output server errors. Default `false`. |
136
- | `trace` | `boolean` | Output [server timing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing). Default `false`. |
133
+ | Option | Description |
134
+ |---------------|-------------------------------------------------------------------------------------------------------------------|
135
+ | `auhorities` | Mapping of authority identifiers to domain names. See [Authorities](documentation/authorities.md). |
136
+ | `class` | Ingress class. |
137
+ | `annotations` | Ingress annotations. |
138
+ | `debug` | Output server errors. Default `false`. |
139
+ | `trace` | Output [server timing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing). Default `false`. |
137
140
 
138
141
  ### Context resources
139
142
 
140
- Exposition annotaion can contain [resource declaration](documentation/tree.md) under the `/` key.
143
+ Exposition annotation can contain [resource declaration](documentation/tree.md) under the `/` key.
141
144
 
142
145
  ```yaml
143
146
  # context.toa.yaml
144
147
 
145
148
  exposition:
146
- host: the.example.com
149
+ authorities:
150
+ example: the.example.com
147
151
  /:
148
152
  /code:
149
153
  GET:
@@ -162,8 +166,9 @@ If component resource branch conflicts with an annotation, the annotation takes
162
166
 
163
167
  ```yaml
164
168
  exposition:
165
- host: the.example.com
166
- host@staging: the.example.dev
169
+ authorities:
170
+ example: the.example.com
171
+ example@staging: the.example.dev
167
172
  class: alb
168
173
  debug@staging: true
169
174
  annotations:
@@ -1,4 +1,4 @@
1
- host: string
1
+ authorities*: <string>
2
2
  class: string
3
3
  annotations: <string>
4
4
  debug: boolean
@@ -1,4 +1,4 @@
1
- verb: /^(GET|POST|PUT|PATCH|DELETE)$/
1
+ verb: /^(GET|POST|PUT|PATCH|DELETE|LOCK|UNLOCK)$/
2
2
  mapping:
3
3
  namespace: string
4
4
  component: string
@@ -1,5 +1,7 @@
1
1
  protected: boolean
2
2
  isolated: boolean
3
+ forward: string
3
4
  routes: [ref:route]
4
5
  methods: [ref:method]
5
6
  directives: [ref:directive]
7
+ version: string
@@ -0,0 +1,25 @@
1
+ type: object
2
+ nullable: true
3
+ properties:
4
+ accept:
5
+ anyOf:
6
+ - type: string
7
+ - type: array
8
+ items:
9
+ type: string
10
+ limit:
11
+ type: string
12
+ pattern: ^(\d+(\.\d+)?)([kmgtKMBGT]i?)?[bB]?$
13
+ trust:
14
+ type: array
15
+ items:
16
+ type: string
17
+ workflow:
18
+ anyOf:
19
+ - &unit
20
+ type: object
21
+ patternProperties:
22
+ ^.+$:
23
+ type: string
24
+ - type: array
25
+ items: *unit
@@ -1,17 +1,11 @@
1
- _: true
2
1
  id?: string
3
2
  criteria?: string
4
3
  sort?: string
5
- omit:
4
+ omit?:
6
5
  $ref: range
7
- default:
8
- value: 0
9
- range: [0, 1000]
10
- limit:
6
+ limit?:
11
7
  $ref: range
12
- default:
13
- value: 10
14
- range: [1, 1000]
15
- required: [value]
16
8
  selectors?: [string]
17
9
  projection?: [string]
10
+ parameters?: [string]
11
+ _: true
@@ -1,8 +1,8 @@
1
1
  export interface Annotation {
2
- host?: string
2
+ authorities: Record<string, string>
3
3
  class?: string
4
4
  annotations?: Record<string, string>
5
- debug: boolean
6
- trace: boolean
5
+ debug?: boolean
6
+ trace?: boolean
7
7
  '/'?: object // parsed and validated by RTD.syntax.parse
8
8
  }
package/source/Branch.ts CHANGED
@@ -5,4 +5,5 @@ export interface Branch {
5
5
  component: string
6
6
  isolated: boolean
7
7
  node: RTD.Node
8
+ version: string
8
9
  }
@@ -18,12 +18,6 @@ export class Composition extends Connector {
18
18
  await composition.connect()
19
19
 
20
20
  this.depends(composition)
21
-
22
- console.info('Composition complete.')
23
- }
24
-
25
- protected override dispose (): void {
26
- console.info('Composition shutdown complete.')
27
21
  }
28
22
  }
29
23
 
package/source/Context.ts CHANGED
@@ -5,4 +5,5 @@ export type Context = RTD.Context<Extension>
5
5
  interface Extension {
6
6
  namespace: string
7
7
  component: string
8
+ version: string
8
9
  }
@@ -65,7 +65,7 @@ it('should throw error if directive family is not found', async () => {
65
65
  }
66
66
 
67
67
  expect(() => factory.create([declaration]))
68
- .toThrowError(`Directive family '${declaration.family}' is not found.`)
68
+ .toThrowError(`Directive family '${declaration.family}' is not found`)
69
69
  })
70
70
 
71
71
  it('should apply directive', async () => {
@@ -17,11 +17,8 @@ export class Directives implements RTD.Directives {
17
17
 
18
18
  const output = await set.family.preflight(set.directives, context, parameters)
19
19
 
20
- if (output !== null) {
21
- await this.settle(context, output)
22
-
20
+ if (output !== null)
23
21
  return output
24
- }
25
22
  }
26
23
 
27
24
  return null
@@ -61,7 +58,7 @@ export class DirectivesFactory implements RTD.DirectiveFactory {
61
58
  const family = this.families[declaration.family]
62
59
 
63
60
  if (family === undefined)
64
- throw new Error(`Directive family '${declaration.family}' is not found.`)
61
+ throw new Error(`Directive family '${declaration.family}' is not found`)
65
62
 
66
63
  const directive = family.create(declaration.name, declaration.value, this.remotes)
67
64
 
@@ -93,5 +90,7 @@ export const shortcuts: RTD.syntax.Shortcuts = new Map([
93
90
  ['id', 'auth:id'],
94
91
  ['role', 'auth:role'],
95
92
  ['rule', 'auth:rule'],
96
- ['incept', 'auth:incept']
93
+ ['incept', 'auth:incept'],
94
+ ['input', 'io:input'],
95
+ ['output', 'io:output']
97
96
  ])
@@ -1,34 +1,41 @@
1
- import { type Component } from '@toa.io/core'
2
- import { type Remotes } from './Remotes'
1
+ import { console } from 'openspan'
3
2
  import { Mapping } from './Mapping'
4
- import { type Context } from './Context'
5
3
  import * as http from './HTTP'
4
+ import type { Introspection, Schema } from './Introspection'
5
+ import type { Remote } from '@toa.io/core'
6
+ import type { Remotes } from './Remotes'
7
+ import type { Context } from './Context'
6
8
  import type * as RTD from './RTD'
7
9
 
8
10
  export class Endpoint implements RTD.Endpoint {
9
11
  private readonly endpoint: string
10
12
  private readonly mapping: Mapping
11
- private readonly discovery: Promise<Component>
12
- private remote: Component | null = null
13
+ private readonly discovery: Promise<Remote>
14
+ private remote: Remote | null = null
13
15
 
14
- public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Component>) {
16
+ public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Remote>) {
15
17
  this.endpoint = endpoint
16
18
  this.mapping = mapping
17
19
  this.discovery = discovery
18
20
  }
19
21
 
20
- public async call
21
- (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
22
+ public async call (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
22
23
  const body = await context.body()
23
24
  const query = this.query(context)
24
25
  const request = this.mapping.fit(body, query, parameters)
25
26
 
26
27
  this.remote ??= await this.discovery
27
28
 
29
+ if (context.debug)
30
+ console.debug('Calling operation', {
31
+ endpoint: this.remote.locator.id + '.' + this.endpoint,
32
+ request
33
+ })
34
+
28
35
  const reply = await this.remote.invoke(this.endpoint, request)
29
36
 
30
37
  if (reply instanceof Error)
31
- throw new http.Conflict(reply)
38
+ throw new http.UnprocessableEntity(reply)
32
39
 
33
40
  const message: http.OutgoingMessage = {}
34
41
 
@@ -51,6 +58,41 @@ export class Endpoint implements RTD.Endpoint {
51
58
  return message
52
59
  }
53
60
 
61
+ public async explain (parameters: RTD.Parameter[]): Promise<Introspection> {
62
+ this.remote ??= await this.discovery
63
+
64
+ // eslint-disable-next-line @typescript-eslint/await-thenable
65
+ const operation = await this.remote.explain(this.endpoint)
66
+
67
+ let route: Record<string, Schema> | null = null
68
+
69
+ if (operation.input?.type === 'object')
70
+ for (const parameter of parameters) {
71
+ const schema = operation.input.properties[parameter.name]
72
+
73
+ // eslint-disable-next-line max-depth
74
+ if (schema !== undefined) {
75
+ route ??= {}
76
+ route[parameter.name] = schema
77
+
78
+ delete operation.input.properties[parameter.name]
79
+ }
80
+ }
81
+
82
+ const query = this.mapping.explain(operation)
83
+ const introspection: Introspection = {}
84
+
85
+ if (route !== null)
86
+ introspection.route = route
87
+
88
+ if (query !== null)
89
+ introspection.query = query
90
+
91
+ Object.assign(introspection, operation)
92
+
93
+ return introspection
94
+ }
95
+
54
96
  public async close (): Promise<void> {
55
97
  this.remote ??= await this.discovery
56
98
 
@@ -61,7 +103,7 @@ export class Endpoint implements RTD.Endpoint {
61
103
  const query: http.Query = Object.fromEntries(context.url.searchParams)
62
104
  const etag = context.request.headers['if-match']
63
105
 
64
- if (etag !== undefined)
106
+ if (etag !== undefined && this.mapping.queryable)
65
107
  query.version = this.version(etag)
66
108
 
67
109
  return query
@@ -71,7 +113,7 @@ export class Endpoint implements RTD.Endpoint {
71
113
  const match = etag.match(ETAG)
72
114
 
73
115
  if (match === null)
74
- throw new http.BadRequest('Invalid ETag.')
116
+ throw new http.BadRequest('Invalid ETag')
75
117
 
76
118
  return Number.parseInt(match.groups!.version)
77
119
  }
@@ -86,21 +128,21 @@ export class EndpointsFactory implements RTD.EndpointsFactory {
86
128
 
87
129
  public create (method: RTD.syntax.Method, context: Context): Endpoint {
88
130
  if (method.mapping === undefined)
89
- throw new Error('Cannot create Endpoint without mapping.')
131
+ throw new Error('Cannot create Endpoint without mapping')
90
132
 
91
133
  const mapping = Mapping.create(method.mapping.query)
92
- const namespace = method.mapping.namespace ?? context.extension?.namespace
93
- const component = method.mapping.component ?? context.extension?.component
134
+ const namespace = method.mapping.namespace ?? context.extension.namespace
135
+ const component = method.mapping.component ?? context.extension.component
94
136
 
95
137
  if (namespace === undefined || component === undefined)
96
- throw new Error('Annotation endpoints must be fully qualified.')
138
+ throw new Error('Annotation endpoints must be fully qualified')
97
139
 
98
- const discovery = this.remotes.discover(namespace, component)
140
+ const discovery = this.remotes.discover(namespace, component, context.extension.version)
99
141
 
100
142
  return new Endpoint(method.mapping.endpoint, mapping, discovery)
101
143
  }
102
144
  }
103
145
 
104
- const ETAG = /^"(?<version>\d{1,32})"$/
146
+ const ETAG = /^(W\/)?"(?<version>\d{1,32})"$/
105
147
 
106
148
  const INTERRUPT = true
package/source/Factory.ts CHANGED
@@ -1,14 +1,19 @@
1
+ import assert from 'node:assert'
2
+ import { decode } from '@toa.io/generic'
1
3
  import { Tenant } from './Tenant'
2
4
  import { Gateway } from './Gateway'
3
5
  import { Remotes } from './Remotes'
4
- import { Tree, syntax } from './RTD'
5
- import { Server } from './HTTP'
6
+ import { Tree } from './RTD'
6
7
  import { EndpointsFactory } from './Endpoint'
7
8
  import { families, interceptors } from './directives'
8
9
  import { DirectivesFactory } from './Directive'
9
10
  import { Composition } from './Composition'
10
11
  import * as root from './root'
11
12
  import { Interception } from './Interception'
13
+ import * as http from './HTTP'
14
+ import type { Manifest } from '@toa.io/norm'
15
+ import type { Branch } from './Branch'
16
+ import type { syntax } from './RTD'
12
17
  import type { Broadcast } from './Gateway'
13
18
  import type { Connector, Locator, extensions } from '@toa.io/core'
14
19
 
@@ -19,23 +24,27 @@ export class Factory implements extensions.Factory {
19
24
  this.boot = boot
20
25
  }
21
26
 
22
- public tenant (locator: Locator, node: syntax.Node): Connector {
27
+ public tenant (locator: Locator, node: syntax.Node, manifest: Manifest): Connector {
23
28
  const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL, locator.id)
24
29
 
25
- return new Tenant(broadcast, locator, node)
30
+ const branch: Branch = {
31
+ namespace: locator.namespace,
32
+ component: locator.name,
33
+ isolated: locator.namespace === 'identity',
34
+ node,
35
+ version: manifest.version
36
+ }
37
+
38
+ return new Tenant(broadcast, branch)
26
39
  }
27
40
 
28
41
  public service (): Connector | null {
29
- const debug = process.env.TOA_EXPOSITION_DEBUG === '1'
30
- const trace = process.env.TOA_EXPOSITION_TRACE === '1'
31
- const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
32
-
33
- const server = Server.create({
34
- methods: syntax.verbs,
35
- debug,
36
- trace
37
- })
42
+ assert.ok(process.env.TOA_EXPOSITION_PROPERTIES,
43
+ 'TOA_EXPOSITION_PROPERTIES is undefined')
38
44
 
45
+ const options = decode<http.Options>(process.env.TOA_EXPOSITION_PROPERTIES)
46
+ const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
47
+ const server = http.Server.create({ ...options })
39
48
  const remotes = new Remotes(this.boot)
40
49
  const node = root.resolve()
41
50
  const methods = new EndpointsFactory(remotes)
package/source/Gateway.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import assert from 'node:assert'
2
+ import { console } from 'openspan'
1
3
  import { type bindings, Connector } from '@toa.io/core'
2
4
  import * as http from './HTTP'
3
5
  import { rethrow } from './exceptions'
4
6
  import type { Interception } from './Interception'
5
- import type { Method, Parameter, Tree } from './RTD'
7
+ import type { Node, Method, Parameter, Tree, Match } from './RTD'
6
8
  import type { Label } from './discovery'
7
9
  import type { Branch } from './Branch'
8
10
 
@@ -10,6 +12,7 @@ export class Gateway extends Connector {
10
12
  private readonly broadcast: Broadcast
11
13
  private readonly tree: Tree
12
14
  private readonly interceptor: Interception
15
+ private readonly merged = new Set<string>()
13
16
 
14
17
  public constructor (broadcast: Broadcast, tree: Tree, interception: Interception) {
15
18
  super()
@@ -28,15 +31,10 @@ export class Gateway extends Connector {
28
31
  if (interception !== null)
29
32
  return interception
30
33
 
31
- const match = this.tree.match(context.url.pathname)
32
-
33
- if (match === null)
34
- throw new http.NotFound()
34
+ const { node, parameters } = this.match(context)
35
35
 
36
- const {
37
- node,
38
- parameters
39
- } = match
36
+ if (context.request.method === 'OPTIONS')
37
+ return await this.explain(node, parameters)
40
38
 
41
39
  if (!(context.request.method in node.methods))
42
40
  throw new http.MethodNotAllowed()
@@ -58,17 +56,41 @@ export class Gateway extends Connector {
58
56
  protected override async open (): Promise<void> {
59
57
  await this.discover()
60
58
 
61
- console.info('Gateway has started and is awaiting resource branches.')
59
+ console.info('Gateway started')
62
60
  }
63
61
 
64
62
  protected override dispose (): void {
65
- console.info('Gateway is closed.')
63
+ console.info('Gateway is closed')
66
64
  }
67
65
 
68
- private async call (method: Method, context: http.Context, parameters: Parameter[]):
69
- Promise<http.OutgoingMessage> {
66
+ private match (context: http.Context): Match {
67
+ const match = this.tree.match(context.url.pathname)
68
+
69
+ if (match === null)
70
+ throw new http.NotFound('Route not found')
71
+
72
+ if (match.node.forward === null)
73
+ return match
74
+
75
+ const destination = match.node.forward.replace(/\/:([^/]+)/g,
76
+ (_, name) => {
77
+ const value = match.parameters.find((parameter) => parameter.name === name)?.value
78
+
79
+ assert.ok(value !== undefined, `Forwarded parameter '${name}' not found`)
80
+
81
+ return `/${value}`
82
+ })
83
+
84
+ const forward = this.tree.match(destination)
85
+
86
+ assert.ok(forward !== null, 'Forwarded route not found')
87
+
88
+ return forward
89
+ }
90
+
91
+ private async call (method: Method, context: http.Context, parameters: Parameter[]): Promise<http.OutgoingMessage> {
70
92
  if (context.url.pathname[context.url.pathname.length - 1] !== '/')
71
- throw new http.NotFound('Trailing slash is required.')
93
+ throw new http.NotFound('Trailing slash is required')
72
94
 
73
95
  if (context.encoder === null)
74
96
  throw new http.NotAcceptable()
@@ -81,19 +103,44 @@ export class Gateway extends Connector {
81
103
  .catch(rethrow) as http.OutgoingMessage
82
104
  }
83
105
 
106
+ private async explain (node: Node, parameters: Parameter[]): Promise<http.OutgoingMessage> {
107
+ const body = await node.explain(parameters)
108
+ const allow = [...Object.keys(node.methods)].join(', ')
109
+ const headers = new Headers({ allow })
110
+
111
+ return { body, headers }
112
+ }
113
+
84
114
  private async discover (): Promise<void> {
85
115
  await this.broadcast.receive<Branch>('expose', this.merge.bind(this))
86
116
  await this.broadcast.transmit<null>('ping', null)
87
117
  }
88
118
 
89
119
  private merge (branch: Branch): void {
120
+ const id = branch.namespace + '.' + branch.component + '@' + branch.version
121
+
122
+ if (this.merged.has(id)) {
123
+ console.debug('Branch already merged, ignoring', {
124
+ namespace: branch.namespace,
125
+ component: branch.component,
126
+ version: branch.version
127
+ })
128
+
129
+ return
130
+ }
131
+
132
+ this.merged.add(id)
133
+
90
134
  try {
91
135
  this.tree.merge(branch.node, branch)
92
136
 
93
- console.info('Resource branch of ' +
94
- `'${branch.namespace}.${branch.component}' has been merged.`)
95
- } catch (exception) {
96
- console.error(exception)
137
+ console.info('Branch merged', {
138
+ namespace: branch.namespace,
139
+ component: branch.component,
140
+ version: branch.version
141
+ })
142
+ } catch (exception: any) {
143
+ console.error('Branch merge exception', exception as Record<string, unknown>)
97
144
  }
98
145
  }
99
146
  }
@@ -1,4 +1,5 @@
1
1
  import Negotiator from 'negotiator'
2
+ import { console } from 'openspan'
2
3
  import { Timing } from './Timing'
3
4
  import { type Format, formats, types } from './formats'
4
5
  import { read } from './messages'
@@ -6,22 +7,29 @@ import type { OutgoingMessage } from './messages'
6
7
  import type * as http from 'node:http'
7
8
 
8
9
  export class Context {
10
+ public readonly authority: string
9
11
  public readonly request: IncomingMessage
10
12
  public readonly url: URL
11
13
  public readonly subtype: string | null = null
12
14
  public readonly encoder: Format | null = null
13
15
  public readonly timing: Timing
16
+ public readonly debug: boolean
14
17
 
15
18
  public readonly pipelines: Pipelines = {
16
19
  body: [],
17
20
  response: []
18
21
  }
19
22
 
20
- public constructor (request: IncomingMessage, trace = false) {
23
+ public constructor (authority: string, request: IncomingMessage, properties: Properties) {
24
+ this.authority = authority
21
25
  this.request = request
22
26
 
23
27
  this.url = new URL(request.url, `https://${request.headers.host}`)
24
- this.timing = new Timing(trace)
28
+ this.timing = new Timing(properties.trace)
29
+ this.debug = properties.debug
30
+
31
+ if (this.debug)
32
+ this.log(request)
25
33
 
26
34
  if (this.request.headers.accept !== undefined) {
27
35
  const match = SUBTYPE.exec(this.request.headers.accept)
@@ -52,6 +60,16 @@ export class Context {
52
60
  ? value
53
61
  : this.pipelines.body.reduce((value, transform) => transform(value), value)
54
62
  }
63
+
64
+ private log (request: IncomingMessage): void {
65
+ const headers = { ...request.headers }
66
+
67
+ if (headers.authorization !== undefined)
68
+ // only scheme
69
+ headers.authorization = headers.authorization.slice(0, headers.authorization.indexOf(' '))
70
+
71
+ console.debug('Received request', { method: request.method, url: request.url, headers })
72
+ }
55
73
  }
56
74
 
57
75
  export interface IncomingMessage extends http.IncomingMessage {
@@ -61,7 +79,12 @@ export interface IncomingMessage extends http.IncomingMessage {
61
79
 
62
80
  interface Pipelines {
63
81
  body: Array<(input: unknown) => unknown>
64
- response: Array<(output: OutgoingMessage) => void>
82
+ response: Array<(output: OutgoingMessage) => void | Promise<void>>
83
+ }
84
+
85
+ interface Properties {
86
+ debug: boolean
87
+ trace: boolean
65
88
  }
66
89
 
67
90
  const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/