@toa.io/extensions.exposition 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (431) hide show
  1. package/components/context.toa.yaml +2 -2
  2. package/components/identity.bans/manifest.toa.yaml +15 -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 +21 -8
  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 +20 -0
  15. package/components/identity.basic/operations/incept.js.map +1 -0
  16. package/components/identity.basic/operations/transit.d.ts +3 -3
  17. package/components/identity.basic/operations/transit.js +5 -3
  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 +2 -0
  21. package/components/identity.basic/source/authenticate.ts +16 -5
  22. package/components/identity.basic/source/incept.ts +32 -0
  23. package/components/identity.basic/source/transit.ts +7 -5
  24. package/components/identity.basic/source/types.ts +2 -0
  25. package/components/identity.federation/manifest.toa.yaml +28 -17
  26. package/components/identity.federation/operations/authenticate.d.ts +2 -2
  27. package/components/identity.federation/operations/authenticate.js +6 -5
  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/jwt.d.ts +4 -5
  33. package/components/identity.federation/operations/lib/jwt.js +3 -3
  34. package/components/identity.federation/operations/lib/jwt.js.map +1 -1
  35. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  36. package/components/identity.federation/operations/types/configuration.d.ts +15 -0
  37. package/components/identity.federation/operations/types/configuration.js +3 -0
  38. package/components/identity.federation/operations/types/configuration.js.map +1 -0
  39. package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +8 -3
  40. package/components/identity.federation/operations/types/context.js +3 -0
  41. package/components/identity.federation/operations/types/context.js.map +1 -0
  42. package/components/identity.federation/operations/types/entity.d.ts +6 -0
  43. package/components/identity.federation/operations/{types.js → types/entity.js} +1 -1
  44. package/components/identity.federation/operations/types/entity.js.map +1 -0
  45. package/components/identity.federation/operations/types/index.d.ts +3 -0
  46. package/components/identity.federation/operations/types/index.js +20 -0
  47. package/components/identity.federation/operations/types/index.js.map +1 -0
  48. package/components/identity.federation/source/authenticate.ts +10 -9
  49. package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
  50. package/components/identity.federation/source/lib/jwt.test.ts +2 -2
  51. package/components/identity.federation/source/lib/jwt.ts +7 -8
  52. package/components/identity.federation/source/types/configuration.ts +16 -0
  53. package/components/identity.federation/source/{types.ts → types/context.ts} +9 -4
  54. package/components/identity.federation/source/types/entity.ts +6 -0
  55. package/components/identity.federation/source/types/index.ts +3 -0
  56. package/components/identity.federation/tsconfig.json +2 -2
  57. package/components/identity.roles/manifest.toa.yaml +18 -5
  58. package/components/identity.roles/operations/grant.d.ts +10 -0
  59. package/components/identity.roles/operations/grant.js +21 -0
  60. package/components/identity.roles/operations/grant.js.map +1 -0
  61. package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
  62. package/components/identity.roles/operations/lib/Entity.js +3 -0
  63. package/components/identity.roles/operations/lib/Entity.js.map +1 -0
  64. package/components/identity.roles/operations/list.d.ts +1 -4
  65. package/components/identity.roles/operations/list.js.map +1 -1
  66. package/components/identity.roles/operations/principal.d.ts +4 -6
  67. package/components/identity.roles/operations/principal.js +6 -1
  68. package/components/identity.roles/operations/principal.js.map +1 -1
  69. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  70. package/components/identity.roles/source/grant.ts +32 -0
  71. package/components/identity.roles/source/lib/Entity.ts +5 -0
  72. package/components/identity.roles/source/list.ts +2 -4
  73. package/components/identity.roles/source/principal.ts +10 -8
  74. package/components/identity.tokens/manifest.toa.yaml +19 -4
  75. package/components/identity.tokens/operations/authenticate.d.ts +2 -2
  76. package/components/identity.tokens/operations/authenticate.js +10 -4
  77. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  78. package/components/identity.tokens/operations/decrypt.js +1 -0
  79. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  80. package/components/identity.tokens/operations/encrypt.js +5 -1
  81. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  82. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  83. package/components/identity.tokens/operations/types.d.ts +8 -2
  84. package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
  85. package/components/identity.tokens/source/authenticate.test.ts +11 -4
  86. package/components/identity.tokens/source/authenticate.ts +12 -5
  87. package/components/identity.tokens/source/decrypt.test.ts +5 -3
  88. package/components/identity.tokens/source/decrypt.ts +9 -8
  89. package/components/identity.tokens/source/encrypt.test.ts +26 -2
  90. package/components/identity.tokens/source/encrypt.ts +5 -1
  91. package/components/identity.tokens/source/types.ts +9 -2
  92. package/components/octets.storage/manifest.toa.yaml +0 -6
  93. package/components/octets.storage/operations/store.js +1 -1
  94. package/documentation/access.md +27 -16
  95. package/documentation/authorities.md +53 -0
  96. package/documentation/cache.md +8 -1
  97. package/documentation/components.md +52 -27
  98. package/documentation/identity.md +17 -22
  99. package/documentation/io.md +56 -0
  100. package/documentation/protocol.md +3 -0
  101. package/documentation/query.md +57 -8
  102. package/documentation/require.md +15 -0
  103. package/documentation/tree.md +22 -4
  104. package/documentation/vary.md +14 -14
  105. package/entity.json +0 -0
  106. package/features/access.feature +83 -56
  107. package/features/annotation.feature +2 -0
  108. package/features/authorities.basic.feature +141 -0
  109. package/features/authorities.feature +32 -0
  110. package/features/authorities.federation.feature +99 -0
  111. package/features/authorities.tokens.feature +118 -0
  112. package/features/body.feature +5 -1
  113. package/features/cache.feature +78 -5
  114. package/features/cors.feature +6 -2
  115. package/features/debug.feature +34 -0
  116. package/features/directives.feature +5 -0
  117. package/features/dynamic.feature +18 -7
  118. package/features/errors.feature +19 -5
  119. package/features/etag.feature +103 -0
  120. package/features/identity.bans.feature +137 -0
  121. package/features/identity.basic.feature +137 -14
  122. package/features/identity.feature +7 -2
  123. package/features/identity.federation.feature +61 -8
  124. package/features/identity.roles.feature +220 -4
  125. package/features/identity.tokens.feature +114 -4
  126. package/features/io.feature +205 -0
  127. package/features/octets.entries.feature +11 -1
  128. package/features/octets.feature +60 -64
  129. package/features/octets.meta.feature +7 -3
  130. package/features/octets.workflows.feature +14 -0
  131. package/features/probes.feature +14 -0
  132. package/features/{queries.feature → query.feature} +50 -3
  133. package/features/require.feature +67 -0
  134. package/features/response.feature +12 -3
  135. package/features/routes.feature +25 -12
  136. package/features/steps/Database.ts +17 -10
  137. package/features/steps/Gateway.ts +24 -4
  138. package/features/steps/IdP.ts +28 -23
  139. package/features/steps/components/echo/manifest.toa.yaml +5 -0
  140. package/features/steps/components/echo/operations/identity.js +7 -0
  141. package/features/steps/components/greeter/manifest.toa.yaml +1 -0
  142. package/features/steps/components/octets.tester/manifest.toa.yaml +1 -0
  143. package/features/steps/components/pots/manifest.toa.yaml +12 -3
  144. package/features/steps/components/sequences/manifest.toa.yaml +1 -0
  145. package/features/steps/components/users.properties/manifest.toa.yaml +2 -1
  146. package/features/streams.feature +1 -0
  147. package/features/timing.feature +69 -0
  148. package/features/vary.feature +105 -3
  149. package/package.json +12 -14
  150. package/readme.md +19 -13
  151. package/schemas/annotation.cos.yaml +2 -1
  152. package/schemas/io/input.cos.yaml +3 -0
  153. package/schemas/io/message.cos.yaml +5 -0
  154. package/schemas/io/output.cos.yaml +5 -0
  155. package/schemas/querystring.cos.yaml +1 -0
  156. package/source/Annotation.ts +3 -2
  157. package/source/Context.ts +6 -4
  158. package/source/Directive.test.ts +7 -7
  159. package/source/Directive.ts +19 -46
  160. package/source/Endpoint.ts +55 -6
  161. package/source/Factory.ts +17 -9
  162. package/source/Gateway.ts +38 -53
  163. package/source/HTTP/Context.ts +89 -0
  164. package/source/HTTP/Server.ts +99 -121
  165. package/source/HTTP/Timing.ts +40 -0
  166. package/source/HTTP/exceptions.ts +7 -1
  167. package/source/HTTP/index.ts +1 -0
  168. package/source/HTTP/messages.test.ts +27 -8
  169. package/source/HTTP/messages.ts +32 -48
  170. package/source/Mapping.ts +12 -8
  171. package/source/Query.test.ts +1 -1
  172. package/source/Query.ts +35 -24
  173. package/source/RTD/Context.ts +7 -10
  174. package/source/RTD/Directives.ts +28 -4
  175. package/source/RTD/Endpoint.ts +6 -4
  176. package/source/RTD/Match.ts +2 -7
  177. package/source/RTD/Method.ts +7 -13
  178. package/source/RTD/Node.ts +13 -14
  179. package/source/RTD/Tree.ts +17 -16
  180. package/source/RTD/factory.ts +3 -6
  181. package/source/Tenant.ts +0 -8
  182. package/source/deployment.ts +33 -17
  183. package/source/directives/auth/Anonymous.ts +3 -2
  184. package/source/directives/auth/Authorization.ts +34 -21
  185. package/source/directives/auth/Delegate.ts +35 -0
  186. package/source/directives/auth/Incept.ts +13 -7
  187. package/source/directives/auth/Role.test.ts +53 -6
  188. package/source/directives/auth/Role.ts +27 -17
  189. package/source/directives/auth/Scheme.ts +2 -2
  190. package/source/directives/auth/types.ts +1 -1
  191. package/source/directives/cache/Cache.ts +5 -5
  192. package/source/directives/cache/Control.ts +48 -22
  193. package/source/directives/cache/types.ts +1 -1
  194. package/source/directives/cors/CORS.ts +18 -10
  195. package/source/directives/dev/Development.ts +4 -4
  196. package/source/directives/index.ts +6 -4
  197. package/source/directives/io/Directive.ts +11 -0
  198. package/source/directives/io/IO.ts +43 -0
  199. package/source/directives/io/Input.ts +50 -0
  200. package/source/directives/io/Message.ts +1 -0
  201. package/source/directives/io/Output.ts +69 -0
  202. package/source/directives/io/index.ts +3 -0
  203. package/source/directives/io/schemas.ts +12 -0
  204. package/source/directives/octets/Context.ts +5 -4
  205. package/source/directives/octets/Delete.ts +23 -11
  206. package/source/directives/octets/Directive.ts +10 -0
  207. package/source/directives/octets/Fetch.ts +33 -17
  208. package/source/directives/octets/List.ts +18 -8
  209. package/source/directives/octets/Octets.ts +9 -9
  210. package/source/directives/octets/Store.ts +29 -19
  211. package/source/directives/octets/Workflow.ts +12 -5
  212. package/source/directives/octets/types.ts +0 -7
  213. package/source/directives/octets/workflows/Workflow.ts +2 -2
  214. package/source/directives/require/Directive.ts +5 -0
  215. package/source/directives/require/Headers.ts +20 -0
  216. package/source/directives/require/Require.ts +28 -0
  217. package/source/directives/require/index.ts +3 -0
  218. package/source/directives/vary/Directive.ts +2 -1
  219. package/source/directives/vary/Embed.ts +14 -8
  220. package/source/directives/vary/Vary.ts +8 -6
  221. package/source/directives/vary/embeddings/Authority.ts +8 -0
  222. package/source/directives/vary/embeddings/Embedding.ts +2 -1
  223. package/source/directives/vary/embeddings/Header.ts +9 -7
  224. package/source/directives/vary/embeddings/Language.ts +2 -2
  225. package/source/directives/vary/embeddings/Parameter.ts +14 -0
  226. package/source/directives/vary/embeddings/index.ts +6 -4
  227. package/source/exceptions.ts +22 -11
  228. package/source/io.ts +2 -2
  229. package/source/root.ts +5 -0
  230. package/source/schemas.ts +1 -1
  231. package/transpiled/Annotation.d.ts +3 -2
  232. package/transpiled/Context.d.ts +6 -4
  233. package/transpiled/Directive.d.ts +8 -21
  234. package/transpiled/Directive.js +11 -14
  235. package/transpiled/Directive.js.map +1 -1
  236. package/transpiled/Endpoint.d.ts +7 -5
  237. package/transpiled/Endpoint.js +60 -2
  238. package/transpiled/Endpoint.js.map +1 -1
  239. package/transpiled/Factory.js +11 -4
  240. package/transpiled/Factory.js.map +1 -1
  241. package/transpiled/Gateway.d.ts +4 -8
  242. package/transpiled/Gateway.js +25 -35
  243. package/transpiled/Gateway.js.map +1 -1
  244. package/transpiled/HTTP/Context.d.ts +31 -0
  245. package/transpiled/HTTP/Context.js +60 -0
  246. package/transpiled/HTTP/Context.js.map +1 -0
  247. package/transpiled/HTTP/Server.d.ts +21 -9
  248. package/transpiled/HTTP/Server.js +98 -100
  249. package/transpiled/HTTP/Server.js.map +1 -1
  250. package/transpiled/HTTP/Timing.d.ts +10 -0
  251. package/transpiled/HTTP/Timing.js +29 -0
  252. package/transpiled/HTTP/Timing.js.map +1 -0
  253. package/transpiled/HTTP/exceptions.d.ts +4 -1
  254. package/transpiled/HTTP/exceptions.js +7 -1
  255. package/transpiled/HTTP/exceptions.js.map +1 -1
  256. package/transpiled/HTTP/index.d.ts +1 -0
  257. package/transpiled/HTTP/index.js +1 -0
  258. package/transpiled/HTTP/index.js.map +1 -1
  259. package/transpiled/HTTP/messages.d.ts +7 -21
  260. package/transpiled/HTTP/messages.js +24 -26
  261. package/transpiled/HTTP/messages.js.map +1 -1
  262. package/transpiled/Mapping.js +11 -8
  263. package/transpiled/Mapping.js.map +1 -1
  264. package/transpiled/Query.d.ts +1 -0
  265. package/transpiled/Query.js +21 -20
  266. package/transpiled/Query.js.map +1 -1
  267. package/transpiled/RTD/Context.d.ts +7 -6
  268. package/transpiled/RTD/Directives.d.ts +19 -4
  269. package/transpiled/RTD/Endpoint.d.ts +6 -4
  270. package/transpiled/RTD/Match.d.ts +2 -4
  271. package/transpiled/RTD/Method.d.ts +7 -7
  272. package/transpiled/RTD/Method.js.map +1 -1
  273. package/transpiled/RTD/Node.d.ts +4 -6
  274. package/transpiled/RTD/Node.js +2 -1
  275. package/transpiled/RTD/Node.js.map +1 -1
  276. package/transpiled/RTD/Tree.d.ts +6 -6
  277. package/transpiled/RTD/Tree.js +4 -1
  278. package/transpiled/RTD/Tree.js.map +1 -1
  279. package/transpiled/RTD/factory.d.ts +2 -4
  280. package/transpiled/RTD/factory.js +1 -1
  281. package/transpiled/RTD/factory.js.map +1 -1
  282. package/transpiled/Tenant.d.ts +0 -1
  283. package/transpiled/Tenant.js +0 -6
  284. package/transpiled/Tenant.js.map +1 -1
  285. package/transpiled/deployment.d.ts +1 -1
  286. package/transpiled/deployment.js +28 -15
  287. package/transpiled/deployment.js.map +1 -1
  288. package/transpiled/directives/auth/Anonymous.js +3 -4
  289. package/transpiled/directives/auth/Anonymous.js.map +1 -1
  290. package/transpiled/directives/auth/Authorization.d.ts +2 -3
  291. package/transpiled/directives/auth/Authorization.js +18 -11
  292. package/transpiled/directives/auth/Authorization.js.map +1 -1
  293. package/transpiled/directives/auth/Delegate.d.ts +8 -0
  294. package/transpiled/directives/auth/Delegate.js +29 -0
  295. package/transpiled/directives/auth/Delegate.js.map +1 -0
  296. package/transpiled/directives/auth/Incept.d.ts +1 -1
  297. package/transpiled/directives/auth/Incept.js +13 -7
  298. package/transpiled/directives/auth/Incept.js.map +1 -1
  299. package/transpiled/directives/auth/Role.d.ts +4 -1
  300. package/transpiled/directives/auth/Role.js +25 -17
  301. package/transpiled/directives/auth/Role.js.map +1 -1
  302. package/transpiled/directives/auth/Scheme.js +2 -2
  303. package/transpiled/directives/auth/Scheme.js.map +1 -1
  304. package/transpiled/directives/cache/Cache.d.ts +3 -3
  305. package/transpiled/directives/cache/Cache.js +3 -3
  306. package/transpiled/directives/cache/Cache.js.map +1 -1
  307. package/transpiled/directives/cache/Control.d.ts +5 -4
  308. package/transpiled/directives/cache/Control.js +32 -15
  309. package/transpiled/directives/cache/Control.js.map +1 -1
  310. package/transpiled/directives/cache/types.d.ts +1 -1
  311. package/transpiled/directives/cors/CORS.d.ts +2 -3
  312. package/transpiled/directives/cors/CORS.js +17 -10
  313. package/transpiled/directives/cors/CORS.js.map +1 -1
  314. package/transpiled/directives/dev/Development.d.ts +3 -3
  315. package/transpiled/directives/dev/Development.js +1 -1
  316. package/transpiled/directives/dev/Development.js.map +1 -1
  317. package/transpiled/directives/index.d.ts +2 -2
  318. package/transpiled/directives/index.js +5 -3
  319. package/transpiled/directives/index.js.map +1 -1
  320. package/transpiled/directives/io/Directive.d.ts +8 -0
  321. package/transpiled/directives/io/Directive.js +3 -0
  322. package/transpiled/directives/io/Directive.js.map +1 -0
  323. package/transpiled/directives/io/IO.d.ts +9 -0
  324. package/transpiled/directives/io/IO.js +33 -0
  325. package/transpiled/directives/io/IO.js.map +1 -0
  326. package/transpiled/directives/io/Input.d.ts +11 -0
  327. package/transpiled/directives/{octets/Permute.js → io/Input.js} +33 -21
  328. package/transpiled/directives/io/Input.js.map +1 -0
  329. package/transpiled/directives/io/Message.d.ts +1 -0
  330. package/transpiled/directives/io/Message.js +3 -0
  331. package/transpiled/directives/io/Message.js.map +1 -0
  332. package/transpiled/directives/io/Output.d.ts +13 -0
  333. package/transpiled/directives/io/Output.js +76 -0
  334. package/transpiled/directives/io/Output.js.map +1 -0
  335. package/transpiled/directives/io/index.d.ts +2 -0
  336. package/transpiled/directives/io/index.js +6 -0
  337. package/transpiled/directives/io/index.js.map +1 -0
  338. package/transpiled/directives/io/schemas.d.ts +7 -0
  339. package/transpiled/directives/io/schemas.js +14 -0
  340. package/transpiled/directives/io/schemas.js.map +1 -0
  341. package/transpiled/directives/octets/Context.d.ts +4 -4
  342. package/transpiled/directives/octets/Context.js +4 -2
  343. package/transpiled/directives/octets/Context.js.map +1 -1
  344. package/transpiled/directives/octets/Delete.d.ts +4 -3
  345. package/transpiled/directives/octets/Delete.js +22 -10
  346. package/transpiled/directives/octets/Delete.js.map +1 -1
  347. package/transpiled/directives/octets/Directive.d.ts +8 -0
  348. package/transpiled/directives/octets/Directive.js +8 -0
  349. package/transpiled/directives/octets/Directive.js.map +1 -0
  350. package/transpiled/directives/octets/Fetch.d.ts +4 -3
  351. package/transpiled/directives/octets/Fetch.js +31 -15
  352. package/transpiled/directives/octets/Fetch.js.map +1 -1
  353. package/transpiled/directives/octets/List.d.ts +4 -3
  354. package/transpiled/directives/octets/List.js +16 -7
  355. package/transpiled/directives/octets/List.js.map +1 -1
  356. package/transpiled/directives/octets/Octets.d.ts +4 -4
  357. package/transpiled/directives/octets/Octets.js +5 -5
  358. package/transpiled/directives/octets/Octets.js.map +1 -1
  359. package/transpiled/directives/octets/Store.d.ts +4 -3
  360. package/transpiled/directives/octets/Store.js +20 -13
  361. package/transpiled/directives/octets/Store.js.map +1 -1
  362. package/transpiled/directives/octets/Workflow.d.ts +4 -3
  363. package/transpiled/directives/octets/Workflow.js +11 -4
  364. package/transpiled/directives/octets/Workflow.js.map +1 -1
  365. package/transpiled/directives/octets/types.d.ts +0 -5
  366. package/transpiled/directives/octets/workflows/Workflow.d.ts +1 -1
  367. package/transpiled/directives/octets/workflows/Workflow.js +2 -2
  368. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  369. package/transpiled/directives/require/Directive.d.ts +4 -0
  370. package/transpiled/directives/require/Directive.js +3 -0
  371. package/transpiled/directives/require/Directive.js.map +1 -0
  372. package/transpiled/directives/require/Headers.d.ts +7 -0
  373. package/transpiled/directives/require/Headers.js +19 -0
  374. package/transpiled/directives/require/Headers.js.map +1 -0
  375. package/transpiled/directives/require/Require.d.ts +9 -0
  376. package/transpiled/directives/require/Require.js +27 -0
  377. package/transpiled/directives/require/Require.js.map +1 -0
  378. package/transpiled/directives/require/index.d.ts +2 -0
  379. package/transpiled/directives/require/index.js +6 -0
  380. package/transpiled/directives/require/index.js.map +1 -0
  381. package/transpiled/directives/vary/Directive.d.ts +2 -1
  382. package/transpiled/directives/vary/Embed.d.ts +2 -1
  383. package/transpiled/directives/vary/Embed.js +8 -6
  384. package/transpiled/directives/vary/Embed.js.map +1 -1
  385. package/transpiled/directives/vary/Vary.d.ts +3 -3
  386. package/transpiled/directives/vary/Vary.js +4 -4
  387. package/transpiled/directives/vary/Vary.js.map +1 -1
  388. package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
  389. package/transpiled/directives/vary/embeddings/Authority.js +10 -0
  390. package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
  391. package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
  392. package/transpiled/directives/vary/embeddings/Header.js +9 -7
  393. package/transpiled/directives/vary/embeddings/Header.js.map +1 -1
  394. package/transpiled/directives/vary/embeddings/Language.js +2 -2
  395. package/transpiled/directives/vary/embeddings/Language.js.map +1 -1
  396. package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
  397. package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
  398. package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
  399. package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
  400. package/transpiled/directives/vary/embeddings/index.js +8 -4
  401. package/transpiled/directives/vary/embeddings/index.js.map +1 -1
  402. package/transpiled/exceptions.d.ts +3 -2
  403. package/transpiled/exceptions.js +13 -7
  404. package/transpiled/exceptions.js.map +1 -1
  405. package/transpiled/io.d.ts +2 -2
  406. package/transpiled/root.js +5 -0
  407. package/transpiled/root.js.map +1 -1
  408. package/transpiled/schemas.d.ts +1 -1
  409. package/transpiled/schemas.js +2 -2
  410. package/transpiled/schemas.js.map +1 -1
  411. package/transpiled/tsconfig.tsbuildinfo +1 -1
  412. package/components/identity.basic/operations/create.d.ts +0 -10
  413. package/components/identity.basic/operations/create.js +0 -10
  414. package/components/identity.basic/operations/create.js.map +0 -1
  415. package/components/identity.basic/source/create.ts +0 -18
  416. package/components/identity.federation/operations/create.d.ts +0 -10
  417. package/components/identity.federation/operations/create.js.map +0 -1
  418. package/components/identity.federation/operations/schemas.d.ts +0 -59
  419. package/components/identity.federation/operations/schemas.js +0 -9
  420. package/components/identity.federation/operations/schemas.js.map +0 -1
  421. package/components/identity.federation/operations/types.js.map +0 -1
  422. package/components/identity.federation/source/schemas.ts +0 -61
  423. package/components/octets.storage/operations/permute.js +0 -7
  424. package/source/HTTP/Server.fixtures.ts +0 -40
  425. package/source/HTTP/Server.test.ts +0 -126
  426. package/source/directives/octets/Permute.ts +0 -37
  427. package/transpiled/HTTP/Server.fixtures.d.ts +0 -10
  428. package/transpiled/HTTP/Server.fixtures.js +0 -31
  429. package/transpiled/HTTP/Server.fixtures.js.map +0 -1
  430. package/transpiled/directives/octets/Permute.d.ts +0 -10
  431. package/transpiled/directives/octets/Permute.js.map +0 -1
@@ -5,6 +5,7 @@ Feature: The Vary directive family
5
5
  """yaml
6
6
  exposition:
7
7
  /:
8
+ io:output: true
8
9
  vary:languages: [en, fr]
9
10
  GET:
10
11
  vary:embed:
@@ -14,6 +15,7 @@ Feature: The Vary directive family
14
15
  When the following request is received:
15
16
  """
16
17
  GET /echo/ HTTP/1.1
18
+ host: nex.toa.io
17
19
  accept: application/yaml
18
20
  accept-language: <accept>
19
21
  """
@@ -43,6 +45,7 @@ Feature: The Vary directive family
43
45
  """yaml
44
46
  exposition:
45
47
  /:
48
+ io:output: true
46
49
  GET:
47
50
  anonymous: true
48
51
  vary:embed:
@@ -52,6 +55,7 @@ Feature: The Vary directive family
52
55
  When the following request is received:
53
56
  """
54
57
  GET /echo/ HTTP/1.1
58
+ host: nex.toa.io
55
59
  accept: application/yaml
56
60
  accept-language: fr
57
61
  """
@@ -62,12 +66,12 @@ Feature: The Vary directive family
62
66
  content-language: fr
63
67
  """
64
68
 
65
-
66
69
  Scenario: Embedding a value of an arbitrary header
67
70
  Given the `echo` is running with the following manifest:
68
71
  """yaml
69
72
  exposition:
70
73
  /:
74
+ io:output: true
71
75
  GET:
72
76
  vary:embed:
73
77
  name: :foo
@@ -76,6 +80,7 @@ Feature: The Vary directive family
76
80
  When the following request is received:
77
81
  """
78
82
  GET /echo/ HTTP/1.1
83
+ host: nex.toa.io
79
84
  accept: application/yaml
80
85
  foo: bar
81
86
  """
@@ -88,11 +93,39 @@ Feature: The Vary directive family
88
93
  Hello bar
89
94
  """
90
95
 
96
+ Scenario: Embedding a `host` header value
97
+ Given the `echo` is running with the following manifest:
98
+ """yaml
99
+ exposition:
100
+ /:
101
+ io:output: true
102
+ GET:
103
+ vary:embed:
104
+ name: :Host
105
+ endpoint: compute
106
+ """
107
+ When the following request is received:
108
+ """
109
+ GET /echo/ HTTP/1.1
110
+ host: nex.toa.io
111
+ accept: application/yaml
112
+ foo: bar
113
+ """
114
+ Then the following reply is sent:
115
+ """
116
+ 200 OK
117
+ content-type: application/yaml
118
+ vary: accept
119
+
120
+ Hello 127.0.0.1:8000
121
+ """
122
+
91
123
  Scenario Outline: Embedding a value from the list of options
92
124
  Given the `echo` is running with the following manifest:
93
125
  """yaml
94
126
  exposition:
95
127
  /:
128
+ io:output: true
96
129
  vary:languages: [en, fr]
97
130
  GET:
98
131
  vary:embed:
@@ -105,6 +138,7 @@ Feature: The Vary directive family
105
138
  When the following request is received:
106
139
  """
107
140
  GET /echo/ HTTP/1.1
141
+ host: nex.toa.io
108
142
  accept: application/yaml
109
143
  <header>: <value>
110
144
  """
@@ -122,11 +156,36 @@ Feature: The Vary directive family
122
156
  | bar | baz |
123
157
  | accept-language | en |
124
158
 
159
+ Scenario: Embedding route parameter
160
+ Given the `echo` is running with the following manifest:
161
+ """yaml
162
+ exposition:
163
+ /:friend:
164
+ io:output: true
165
+ GET:
166
+ vary:embed:
167
+ name: /:friend
168
+ endpoint: compute
169
+ """
170
+ When the following request is received:
171
+ """
172
+ GET /echo/Ken/ HTTP/1.1
173
+ host: nex.toa.io
174
+ accept: text/plain
175
+ """
176
+ Then the following reply is sent:
177
+ """
178
+ 200 OK
179
+
180
+ Hello Ken
181
+ """
182
+
125
183
  Scenario: Adding headers used by defined embeddings to CORS permissions
126
184
  Given the `echo` is running with the following manifest:
127
185
  """yaml
128
186
  exposition:
129
187
  /:
188
+ io:output: true
130
189
  vary:languages: [en, fr]
131
190
  GET:
132
191
  vary:embed:
@@ -140,11 +199,54 @@ Feature: The Vary directive family
140
199
  When the following request is received:
141
200
  """
142
201
  OPTIONS / HTTP/1.1
143
- origin: http://example.com
202
+ host: nex.toa.io
203
+ origin: https://example.com
144
204
  access-control-request-headers: whatever
145
205
  """
146
206
  Then the following reply is sent:
147
207
  """
148
208
  204 No Content
149
- access-control-allow-headers: accept, authorization, content-type, accept-language, foo, bar
209
+ access-control-allow-headers: accept, authorization, content-type, etag, if-match, if-none-match, accept-language, foo, bar
150
210
  """
211
+
212
+ Scenario: Embedding authority
213
+ Given the annotation:
214
+ """yaml
215
+ authorities:
216
+ one: the.one.com
217
+ two: the.two.com
218
+ """
219
+ Given the `echo` is running with the following manifest:
220
+ """yaml
221
+ exposition:
222
+ /:
223
+ io:output: true
224
+ GET:
225
+ vary:embed:
226
+ name: authority
227
+ endpoint: compute
228
+ """
229
+ When the following request is received:
230
+ """
231
+ GET /echo/ HTTP/1.1
232
+ host: the.one.com
233
+ accept: text/plain
234
+ """
235
+ Then the following reply is sent:
236
+ """
237
+ 200 OK
238
+
239
+ Hello one
240
+ """
241
+ When the following request is received:
242
+ """
243
+ GET /echo/ HTTP/1.1
244
+ host: the.two.com
245
+ accept: text/plain
246
+ """
247
+ Then the following reply is sent:
248
+ """
249
+ 200 OK
250
+
251
+ Hello two
252
+ """
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/extensions.exposition",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0-alpha.30",
4
4
  "description": "Toa Exposition",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -17,13 +17,11 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "@toa.io/core": "1.0.0-alpha.3",
21
- "@toa.io/generic": "1.0.0-alpha.3",
22
- "@toa.io/schemas": "1.0.0-alpha.3",
23
- "@toa.io/streams": "1.0.0-alpha.3",
20
+ "@toa.io/core": "1.0.0-alpha.30",
21
+ "@toa.io/generic": "1.0.0-alpha.30",
22
+ "@toa.io/schemas": "1.0.0-alpha.30",
24
23
  "bcryptjs": "2.4.3",
25
24
  "error-value": "0.3.0",
26
- "express": "4.18.2",
27
25
  "js-yaml": "4.1.0",
28
26
  "matchacho": "0.3.5",
29
27
  "msgpackr": "1.10.1",
@@ -36,21 +34,21 @@
36
34
  },
37
35
  "scripts": {
38
36
  "test": "jest",
39
- "transpile": "tsc && npm run transpile:basic && npm run transpile:tokens && npm run transpile:roles && npm run transpile:federation",
37
+ "transpile": "tsc && npm run transpile:bans && npm run transpile:basic && npm run transpile:tokens && npm run transpile:roles && npm run transpile:federation",
38
+ "transpile:bans": "tsc -p ./components/identity.bans",
40
39
  "transpile:basic": "tsc -p ./components/identity.basic",
41
- "pretranspile:federation": "js-yaml components/identity.federation/manifest.toa.yaml | jq -M '{ type: \"object\", properties: {configuration: .configuration.schema, entity: .entity.schema }, additionalProperties: false}' > schemas.json && json2ts -i schemas.json -o components/identity.federation/source/schemas.ts && rm schemas.json",
42
- "transpile:federation": "tsc -p ./components/identity.federation",
43
40
  "transpile:tokens": "tsc -p ./components/identity.tokens",
44
41
  "transpile:roles": "tsc -p ./components/identity.roles",
45
- "features": "cucumber-js"
42
+ "transpile:federation": "tsc -p ./components/identity.federation",
43
+ "features": "cucumber-js",
44
+ "features:security": "cucumber-js --tags @security"
46
45
  },
47
46
  "devDependencies": {
48
- "@toa.io/agent": "1.0.0-alpha.3",
49
- "@toa.io/extensions.storages": "1.0.0-alpha.3",
47
+ "@toa.io/agent": "1.0.0-alpha.30",
48
+ "@toa.io/extensions.storages": "1.0.0-alpha.30",
50
49
  "@types/bcryptjs": "2.4.3",
51
50
  "@types/cors": "2.8.13",
52
- "@types/express": "4.17.17",
53
51
  "@types/negotiator": "0.6.1"
54
52
  },
55
- "gitHead": "e36ac7871fc14d15863aaf8f9bbdeace8bdfa9f0"
53
+ "gitHead": "29cc19358f35fbe9229dced979724f7a26538013"
56
54
  }
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,32 +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`. |
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`. |
136
140
 
137
141
  ### Context resources
138
142
 
139
- 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.
140
144
 
141
145
  ```yaml
142
146
  # context.toa.yaml
143
147
 
144
148
  exposition:
145
- host: the.example.com
149
+ authorities:
150
+ example: the.example.com
146
151
  /:
147
152
  /code:
148
153
  GET:
@@ -161,8 +166,9 @@ If component resource branch conflicts with an annotation, the annotation takes
161
166
 
162
167
  ```yaml
163
168
  exposition:
164
- host: the.example.com
165
- host@staging: the.example.dev
169
+ authorities:
170
+ example: the.example.com
171
+ example@staging: the.example.dev
166
172
  class: alb
167
173
  debug@staging: true
168
174
  annotations:
@@ -1,5 +1,6 @@
1
- host: string
1
+ authorities*: <string>
2
2
  class: string
3
3
  annotations: <string>
4
4
  debug: boolean
5
+ trace: boolean
5
6
  /: ~
@@ -0,0 +1,3 @@
1
+ type: array
2
+ items:
3
+ type: string
@@ -0,0 +1,5 @@
1
+ oneOf:
2
+ - type: object
3
+ - type: array
4
+ items:
5
+ type: object
@@ -0,0 +1,5 @@
1
+ oneOf:
2
+ - type: boolean
3
+ - type: array
4
+ items:
5
+ type: string
@@ -3,3 +3,4 @@ criteria: string
3
3
  sort: string
4
4
  omit: number
5
5
  limit: number
6
+ version: number
@@ -1,7 +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
5
+ debug?: boolean
6
+ trace?: boolean
6
7
  '/'?: object // parsed and validated by RTD.syntax.parse
7
8
  }
package/source/Context.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { type Endpoint } from './Endpoint'
2
- import { type Directives } from './Directive'
3
- import { type Branch } from './Branch'
4
1
  import type * as RTD from './RTD'
5
2
 
6
- export type Context = RTD.Context<Endpoint, Directives, Branch>
3
+ export type Context = RTD.Context<Extension>
4
+
5
+ interface Extension {
6
+ namespace: string
7
+ component: string
8
+ }
@@ -1,11 +1,11 @@
1
1
  import assert from 'node:assert'
2
2
  import { generate } from 'randomstring'
3
- import { DirectivesFactory, type Family } from './Directive'
4
- import { type syntax } from './RTD'
5
- import { type IncomingMessage } from './HTTP'
6
- import { type Remotes } from './Remotes'
3
+ import { DirectivesFactory } from './Directive'
4
+ import type { syntax, DirectiveFamily } from './RTD'
5
+ import type { Remotes } from './Remotes'
6
+ import type { Context } from './HTTP'
7
7
 
8
- const families: Array<jest.MockedObjectDeep<Family>> = [
8
+ const families: Array<jest.MockedObjectDeep<DirectiveFamily>> = [
9
9
  {
10
10
  name: 'foo',
11
11
  mandatory: true,
@@ -76,7 +76,7 @@ it('should apply directive', async () => {
76
76
  }
77
77
 
78
78
  const directives = factory.create([declaration])
79
- const request = generate() as unknown as IncomingMessage
79
+ const request = generate() as unknown as Context
80
80
  const directive = families[0].create.mock.results[0].value
81
81
 
82
82
  await directives.preflight(request, [])
@@ -89,7 +89,7 @@ it('should apply directive', async () => {
89
89
 
90
90
  it('should apply mandatory families', async () => {
91
91
  const directives = factory.create([])
92
- const request = generate() as unknown as IncomingMessage
92
+ const request = generate() as unknown as Context
93
93
 
94
94
  await directives.preflight(request, [])
95
95
 
@@ -1,49 +1,42 @@
1
- import type { IncomingMessage, OutgoingMessage } from './HTTP'
1
+ import type { Context, OutgoingMessage } from './HTTP'
2
2
  import type { Remotes } from './Remotes'
3
3
  import type { Output } from './io'
4
4
  import type * as RTD from './RTD'
5
5
 
6
- export class Directives implements RTD.Directives<Directives> {
7
- private readonly sets: DirectiveSet[]
6
+ export class Directives implements RTD.Directives {
7
+ private readonly sets: RTD.DirectiveSet[]
8
8
 
9
- public constructor (sets: DirectiveSet[]) {
9
+ public constructor (sets: RTD.DirectiveSet[]) {
10
10
  this.sets = sets
11
11
  }
12
12
 
13
- public async preflight (request: IncomingMessage, parameters: RTD.Parameter[]): Promise<Output> {
13
+ public async preflight (context: Context, parameters: RTD.Parameter[]): Promise<Output> {
14
14
  for (const set of this.sets) {
15
15
  if (set.family.preflight === undefined)
16
16
  continue
17
17
 
18
- const output = await set.family.preflight(set.directives, request, parameters)
19
-
20
- if (output !== null) {
21
- await this.settle(request, output)
18
+ const output = await set.family.preflight(set.directives, context, parameters)
22
19
 
20
+ if (output !== null)
23
21
  return output
24
- }
25
22
  }
26
23
 
27
24
  return null
28
25
  }
29
26
 
30
- public async settle (request: IncomingMessage, response: OutgoingMessage): Promise<void> {
27
+ public async settle (context: Context, response: OutgoingMessage): Promise<void> {
31
28
  for (const set of this.sets)
32
29
  if (set.family.settle !== undefined)
33
- await set.family.settle(set.directives, request, response)
34
- }
35
-
36
- public merge (directives: Directives): void {
37
- this.sets.push(...directives.sets)
30
+ await set.family.settle(set.directives, context, response)
38
31
  }
39
32
  }
40
33
 
41
- export class DirectivesFactory implements RTD.DirectivesFactory<Directives> {
42
- private readonly remtoes: Remotes
43
- private readonly families: Record<string, Family> = {}
34
+ export class DirectivesFactory implements RTD.DirectiveFactory {
35
+ private readonly remotes: Remotes
36
+ private readonly families: Record<string, RTD.DirectiveFamily> = {}
44
37
  private readonly mandatory: string[] = []
45
38
 
46
- public constructor (families: Family[], remotes: Remotes) {
39
+ public constructor (families: RTD.DirectiveFamily[], remotes: Remotes) {
47
40
  for (const family of families) {
48
41
  this.families[family.name] = family
49
42
 
@@ -51,7 +44,7 @@ export class DirectivesFactory implements RTD.DirectivesFactory<Directives> {
51
44
  this.mandatory.push(family.name)
52
45
  }
53
46
 
54
- this.remtoes = remotes
47
+ this.remotes = remotes
55
48
  }
56
49
 
57
50
  public create (declarations: RTD.syntax.Directive[]): Directives {
@@ -67,14 +60,14 @@ export class DirectivesFactory implements RTD.DirectivesFactory<Directives> {
67
60
  if (family === undefined)
68
61
  throw new Error(`Directive family '${declaration.family}' is not found.`)
69
62
 
70
- const directive = family.create(declaration.name, declaration.value, this.remtoes)
63
+ const directive = family.create(declaration.name, declaration.value, this.remotes)
71
64
 
72
65
  groups[family.name] ??= []
73
66
  groups[family.name].push(directive)
74
67
  mandatory.delete(family.name)
75
68
  }
76
69
 
77
- const sets: DirectiveSet[] = []
70
+ const sets: RTD.DirectiveSet[] = []
78
71
 
79
72
  for (const family of mandatory)
80
73
  sets.push({
@@ -97,27 +90,7 @@ export const shortcuts: RTD.syntax.Shortcuts = new Map([
97
90
  ['id', 'auth:id'],
98
91
  ['role', 'auth:role'],
99
92
  ['rule', 'auth:rule'],
100
- ['incept', 'auth:incept']
93
+ ['incept', 'auth:incept'],
94
+ ['input', 'io:input'],
95
+ ['output', 'io:output']
101
96
  ])
102
-
103
- export interface Family<TDirective = any, TExtension = any> {
104
- readonly name: string
105
- readonly mandatory: boolean
106
-
107
- // produce: (declarations: RTD.syntax.Directive[], remotes: Remotes) => TDirective[]
108
-
109
- create: (name: string, value: any, remotes: Remotes) => TDirective
110
-
111
- preflight?: (directives: TDirective[],
112
- request: IncomingMessage & TExtension,
113
- parameters: RTD.Parameter[]) => Output | Promise<Output>
114
-
115
- settle?: (directives: TDirective[],
116
- request: IncomingMessage & TExtension,
117
- response: OutgoingMessage) => void | Promise<void>
118
- }
119
-
120
- interface DirectiveSet {
121
- family: Family
122
- directives: any[]
123
- }
@@ -1,11 +1,11 @@
1
- import { type Component, type Reply } from '@toa.io/core'
1
+ import { type Component } from '@toa.io/core'
2
2
  import { type Remotes } from './Remotes'
3
3
  import { Mapping } from './Mapping'
4
4
  import { type Context } from './Context'
5
+ import * as http from './HTTP'
5
6
  import type * as RTD from './RTD'
6
- import type * as http from './HTTP'
7
7
 
8
- export class Endpoint implements RTD.Endpoint<Endpoint> {
8
+ export class Endpoint implements RTD.Endpoint {
9
9
  private readonly endpoint: string
10
10
  private readonly mapping: Mapping
11
11
  private readonly discovery: Promise<Component>
@@ -17,12 +17,40 @@ export class Endpoint implements RTD.Endpoint<Endpoint> {
17
17
  this.discovery = discovery
18
18
  }
19
19
 
20
- public async call (body: any, query: http.Query, parameters: RTD.Parameter[]): Promise<Reply> {
20
+ public async call (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
21
+ const body = await context.body()
22
+ const query = this.query(context)
21
23
  const request = this.mapping.fit(body, query, parameters)
22
24
 
23
25
  this.remote ??= await this.discovery
24
26
 
25
- return await this.remote.invoke(this.endpoint, request)
27
+ const reply = await this.remote.invoke(this.endpoint, request)
28
+
29
+ if (context.debug)
30
+ console.debug('Call', `${this.remote.locator.id}.${this.endpoint}`, request)
31
+
32
+ if (reply instanceof Error)
33
+ throw new http.UnprocessableEntity(reply)
34
+
35
+ const message: http.OutgoingMessage = {}
36
+
37
+ if (typeof reply === 'object' && reply !== null && '_version' in reply) {
38
+ const etag = context.request.headers['if-none-match']
39
+
40
+ message.headers ??= new Headers()
41
+
42
+ if (etag !== undefined && reply._version === this.version(etag)) {
43
+ message.status = 304
44
+ message.headers.set('etag', etag)
45
+
46
+ return message
47
+ } else
48
+ message.headers.set('etag', `"${reply._version.toString()}"`)
49
+ }
50
+
51
+ message.body = reply
52
+
53
+ return message
26
54
  }
27
55
 
28
56
  public async close (): Promise<void> {
@@ -30,9 +58,28 @@ export class Endpoint implements RTD.Endpoint<Endpoint> {
30
58
 
31
59
  await this.remote.disconnect(INTERRUPT)
32
60
  }
61
+
62
+ private query (context: http.Context): http.Query {
63
+ const query: http.Query = Object.fromEntries(context.url.searchParams)
64
+ const etag = context.request.headers['if-match']
65
+
66
+ if (etag !== undefined)
67
+ query.version = this.version(etag)
68
+
69
+ return query
70
+ }
71
+
72
+ private version (etag: string): number {
73
+ const match = etag.match(ETAG)
74
+
75
+ if (match === null)
76
+ throw new http.BadRequest('Invalid ETag.')
77
+
78
+ return Number.parseInt(match.groups!.version)
79
+ }
33
80
  }
34
81
 
35
- export class EndpointsFactory implements RTD.EndpointsFactory<Endpoint> {
82
+ export class EndpointsFactory implements RTD.EndpointsFactory {
36
83
  private readonly remotes: Remotes
37
84
 
38
85
  public constructor (remotes: Remotes) {
@@ -56,4 +103,6 @@ export class EndpointsFactory implements RTD.EndpointsFactory<Endpoint> {
56
103
  }
57
104
  }
58
105
 
106
+ const ETAG = /^"(?<version>\d{1,32})"$/
107
+
59
108
  const INTERRUPT = true