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

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