@toa.io/extensions.exposition 1.0.0-alpha.27 → 1.0.0-alpha.271

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 (913) hide show
  1. package/CHANGELOG.md +188 -0
  2. package/components/exposition.octets/manifest.toa.yaml +29 -0
  3. package/components/exposition.octets/operations/get.js +7 -0
  4. package/components/exposition.octets/operations/head.js +7 -0
  5. package/components/exposition.octets/operations/put.js +135 -0
  6. package/components/exposition.stash/manifest.toa.yaml +21 -0
  7. package/components/exposition.stash/operations/meter.js +7 -0
  8. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -1
  9. package/components/identity.basic/manifest.toa.yaml +93 -11
  10. package/components/identity.basic/operations/add.d.ts +3 -0
  11. package/components/identity.basic/operations/add.js +17 -0
  12. package/components/identity.basic/operations/add.js.map +1 -0
  13. package/components/identity.basic/operations/authenticate.js +2 -2
  14. package/components/identity.basic/operations/authenticate.js.map +1 -1
  15. package/components/identity.basic/operations/check.d.ts +7 -0
  16. package/components/identity.basic/operations/check.js +15 -0
  17. package/components/identity.basic/operations/check.js.map +1 -0
  18. package/components/identity.basic/operations/delete.d.ts +7 -0
  19. package/components/identity.basic/operations/delete.js +11 -0
  20. package/components/identity.basic/operations/delete.js.map +1 -0
  21. package/components/identity.basic/operations/incept.d.ts +1 -1
  22. package/components/identity.basic/operations/incept.js +9 -3
  23. package/components/identity.basic/operations/incept.js.map +1 -1
  24. package/components/identity.basic/operations/info.d.ts +10 -0
  25. package/components/identity.basic/operations/info.js +11 -0
  26. package/components/identity.basic/operations/info.js.map +1 -0
  27. package/components/identity.basic/operations/transit.d.ts +2 -2
  28. package/components/identity.basic/operations/transit.js +11 -7
  29. package/components/identity.basic/operations/transit.js.map +1 -1
  30. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  31. package/components/identity.basic/operations/types.d.ts +18 -7
  32. package/components/identity.basic/source/add.ts +15 -0
  33. package/components/identity.basic/source/authenticate.ts +2 -2
  34. package/components/identity.basic/source/check.ts +20 -0
  35. package/components/identity.basic/source/delete.ts +15 -0
  36. package/components/identity.basic/source/incept.ts +10 -4
  37. package/components/identity.basic/source/info.ts +19 -0
  38. package/components/identity.basic/source/transit.ts +14 -11
  39. package/components/identity.basic/source/types.ts +20 -7
  40. package/components/identity.credentials/manifest.toa.yaml +57 -0
  41. package/components/identity.credentials/operations/list.d.ts +51 -0
  42. package/components/identity.credentials/operations/list.js +32 -0
  43. package/components/identity.credentials/operations/list.js.map +1 -0
  44. package/components/identity.credentials/operations/tsconfig.tsbuildinfo +1 -0
  45. package/components/identity.credentials/source/list.test.ts +47 -0
  46. package/components/identity.credentials/source/list.ts +87 -0
  47. package/components/identity.credentials/tsconfig.json +7 -0
  48. package/components/identity.federation/events/principal.js +2 -2
  49. package/components/identity.federation/manifest.toa.yaml +110 -40
  50. package/components/identity.federation/operations/authenticate.d.ts +16 -3
  51. package/components/identity.federation/operations/authenticate.js +24 -16
  52. package/components/identity.federation/operations/authenticate.js.map +1 -1
  53. package/components/identity.federation/operations/create.d.ts +8 -0
  54. package/components/identity.federation/operations/create.js +27 -0
  55. package/components/identity.federation/operations/create.js.map +1 -0
  56. package/components/identity.federation/operations/decode.d.ts +3 -0
  57. package/components/identity.federation/operations/decode.js +13 -0
  58. package/components/identity.federation/operations/decode.js.map +1 -0
  59. package/components/identity.federation/operations/delete.d.ts +8 -0
  60. package/components/identity.federation/operations/delete.js +11 -0
  61. package/components/identity.federation/operations/delete.js.map +1 -0
  62. package/components/identity.federation/operations/incept.d.ts +6 -6
  63. package/components/identity.federation/operations/incept.js +5 -9
  64. package/components/identity.federation/operations/incept.js.map +1 -1
  65. package/components/identity.federation/operations/lib/Configuration.d.ts +39 -0
  66. package/components/identity.federation/operations/lib/Configuration.js +3 -0
  67. package/components/identity.federation/operations/lib/Configuration.js.map +1 -0
  68. package/components/identity.federation/operations/lib/Ctx.d.ts +8 -0
  69. package/{transpiled/directives/vary/embeddings/Embedding.js → components/identity.federation/operations/lib/Ctx.js} +1 -1
  70. package/components/identity.federation/operations/lib/Ctx.js.map +1 -0
  71. package/components/identity.federation/operations/lib/Payload.d.ts +5 -0
  72. package/components/identity.federation/operations/lib/Payload.js +3 -0
  73. package/components/identity.federation/operations/lib/Payload.js.map +1 -0
  74. package/components/identity.federation/operations/lib/decode.d.ts +3 -0
  75. package/components/identity.federation/operations/lib/decode.js +22 -0
  76. package/components/identity.federation/operations/lib/decode.js.map +1 -0
  77. package/components/identity.federation/operations/lib/discovery.d.ts +5 -0
  78. package/components/identity.federation/operations/lib/discovery.js +39 -0
  79. package/components/identity.federation/operations/lib/discovery.js.map +1 -0
  80. package/components/identity.federation/operations/lib/errors.d.ts +11 -0
  81. package/components/identity.federation/operations/lib/errors.js +15 -0
  82. package/components/identity.federation/operations/lib/errors.js.map +1 -0
  83. package/components/identity.federation/operations/lib/exchange.d.ts +3 -0
  84. package/components/identity.federation/operations/lib/exchange.js +108 -0
  85. package/components/identity.federation/operations/lib/exchange.js.map +1 -0
  86. package/components/identity.federation/operations/lib/index.d.ts +4 -0
  87. package/components/identity.federation/operations/lib/index.js +10 -0
  88. package/components/identity.federation/operations/lib/index.js.map +1 -0
  89. package/components/identity.federation/operations/lib/jose.d.ts +41 -0
  90. package/components/identity.federation/operations/lib/{assertions-as-values.js → jose.js} +4 -22
  91. package/components/identity.federation/operations/lib/jose.js.map +1 -0
  92. package/components/identity.federation/operations/lib/resolve.d.ts +3 -0
  93. package/components/identity.federation/operations/lib/resolve.js +17 -0
  94. package/components/identity.federation/operations/lib/resolve.js.map +1 -0
  95. package/components/identity.federation/operations/list.d.ts +7 -0
  96. package/components/identity.federation/operations/list.js +15 -0
  97. package/components/identity.federation/operations/list.js.map +1 -0
  98. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  99. package/components/identity.federation/operations/types/Scheme.d.ts +1 -0
  100. package/components/identity.federation/operations/types/Scheme.js +3 -0
  101. package/components/identity.federation/operations/types/Scheme.js.map +1 -0
  102. package/components/identity.federation/operations/types/configuration.d.ts +20 -0
  103. package/components/identity.federation/operations/types/configuration.js +3 -0
  104. package/components/identity.federation/operations/types/configuration.js.map +1 -0
  105. package/components/identity.federation/operations/types/context.d.ts +35 -0
  106. package/components/identity.federation/operations/types/context.js +3 -0
  107. package/components/identity.federation/operations/types/context.js.map +1 -0
  108. package/components/identity.federation/operations/types/entity.d.ts +9 -0
  109. package/components/identity.federation/operations/types/entity.js +3 -0
  110. package/components/identity.federation/operations/types/entity.js.map +1 -0
  111. package/components/identity.federation/operations/types/index.d.ts +4 -0
  112. package/components/identity.federation/operations/types/index.js +21 -0
  113. package/components/identity.federation/operations/types/index.js.map +1 -0
  114. package/components/identity.federation/source/authenticate.ts +41 -21
  115. package/components/identity.federation/source/create.ts +39 -0
  116. package/components/identity.federation/source/decode.ts +11 -0
  117. package/components/identity.federation/source/delete.ts +16 -0
  118. package/components/identity.federation/source/incept.ts +9 -17
  119. package/components/identity.federation/source/lib/Configuration.ts +39 -0
  120. package/components/identity.federation/source/lib/Ctx.ts +9 -0
  121. package/components/identity.federation/source/lib/Payload.ts +6 -0
  122. package/components/identity.federation/source/lib/decode.ts +27 -0
  123. package/components/identity.federation/source/lib/discovery.test.ts +45 -0
  124. package/components/identity.federation/source/lib/discovery.ts +49 -0
  125. package/components/identity.federation/source/lib/errors.ts +12 -0
  126. package/components/identity.federation/source/lib/exchange.ts +116 -0
  127. package/components/identity.federation/source/lib/index.ts +4 -0
  128. package/components/identity.federation/source/lib/jose.d.ts +1 -0
  129. package/components/identity.federation/source/lib/jose.js +5 -0
  130. package/components/identity.federation/source/lib/resolve.ts +17 -0
  131. package/components/identity.federation/source/list.test.ts +22 -0
  132. package/components/identity.federation/source/list.ts +17 -0
  133. package/components/identity.federation/source/types/Scheme.ts +1 -0
  134. package/components/identity.federation/source/types/configuration.ts +21 -0
  135. package/components/identity.federation/source/types/context.ts +38 -0
  136. package/components/identity.federation/source/types/entity.ts +9 -0
  137. package/components/identity.federation/source/types/index.ts +4 -0
  138. package/components/identity.federation/tsconfig.json +1 -3
  139. package/components/identity.keys/manifest.toa.yaml +58 -0
  140. package/components/identity.keys/operations/create.d.ts +22 -0
  141. package/components/identity.keys/operations/create.js +16 -0
  142. package/components/identity.keys/operations/create.js.map +1 -0
  143. package/components/identity.keys/operations/tsconfig.tsbuildinfo +1 -0
  144. package/components/identity.keys/source/create.ts +35 -0
  145. package/components/identity.keys/tsconfig.json +9 -0
  146. package/components/identity.otp/manifest.toa.yaml +69 -0
  147. package/components/identity.otp/operations/authenticate.d.ts +12 -0
  148. package/components/identity.otp/operations/authenticate.js +31 -0
  149. package/components/identity.otp/operations/authenticate.js.map +1 -0
  150. package/components/identity.otp/operations/issue.d.ts +12 -0
  151. package/components/identity.otp/operations/issue.js +22 -0
  152. package/components/identity.otp/operations/issue.js.map +1 -0
  153. package/components/identity.otp/operations/lib/Context.d.ts +13 -0
  154. package/components/identity.otp/operations/lib/Context.js +3 -0
  155. package/components/identity.otp/operations/lib/Context.js.map +1 -0
  156. package/components/identity.otp/operations/lib/Entity.d.ts +6 -0
  157. package/components/identity.otp/operations/lib/Entity.js +3 -0
  158. package/components/identity.otp/operations/lib/Entity.js.map +1 -0
  159. package/components/identity.otp/operations/lib/index.d.ts +1 -0
  160. package/components/identity.otp/operations/lib/index.js +3 -0
  161. package/components/identity.otp/operations/lib/index.js.map +1 -0
  162. package/components/identity.otp/operations/tsconfig.tsbuildinfo +1 -0
  163. package/components/identity.otp/source/authenticate.ts +48 -0
  164. package/components/identity.otp/source/issue.ts +34 -0
  165. package/components/identity.otp/source/lib/Context.ts +14 -0
  166. package/components/identity.otp/source/lib/Entity.ts +6 -0
  167. package/components/identity.otp/source/lib/index.ts +1 -0
  168. package/components/identity.otp/tsconfig.json +9 -0
  169. package/components/identity.passkeys/manifest.toa.yaml +276 -0
  170. package/components/identity.passkeys/operations/authenticate.d.ts +16 -0
  171. package/components/identity.passkeys/operations/authenticate.js +34 -0
  172. package/components/identity.passkeys/operations/authenticate.js.map +1 -0
  173. package/components/identity.passkeys/operations/challenge.d.ts +35 -0
  174. package/components/identity.passkeys/operations/challenge.js +73 -0
  175. package/components/identity.passkeys/operations/challenge.js.map +1 -0
  176. package/components/identity.passkeys/operations/create.d.ts +19 -0
  177. package/components/identity.passkeys/operations/create.js +58 -0
  178. package/components/identity.passkeys/operations/create.js.map +1 -0
  179. package/components/identity.passkeys/operations/delete.d.ts +8 -0
  180. package/components/identity.passkeys/operations/delete.js +12 -0
  181. package/components/identity.passkeys/operations/delete.js.map +1 -0
  182. package/components/identity.passkeys/operations/lib/const.d.ts +1 -0
  183. package/components/identity.passkeys/operations/lib/const.js +5 -0
  184. package/components/identity.passkeys/operations/lib/const.js.map +1 -0
  185. package/components/identity.passkeys/operations/list.d.ts +7 -0
  186. package/components/identity.passkeys/operations/list.js +15 -0
  187. package/components/identity.passkeys/operations/list.js.map +1 -0
  188. package/components/identity.passkeys/operations/tsconfig.tsbuildinfo +1 -0
  189. package/components/identity.passkeys/operations/types/Configuration.d.ts +6 -0
  190. package/components/identity.passkeys/operations/types/Configuration.js +3 -0
  191. package/components/identity.passkeys/operations/types/Configuration.js.map +1 -0
  192. package/components/identity.passkeys/operations/types/Context.d.ts +15 -0
  193. package/components/identity.passkeys/operations/types/Context.js +3 -0
  194. package/components/identity.passkeys/operations/types/Context.js.map +1 -0
  195. package/components/identity.passkeys/operations/types/Passkey.d.ts +13 -0
  196. package/components/identity.passkeys/operations/types/Passkey.js +3 -0
  197. package/components/identity.passkeys/operations/types/Passkey.js.map +1 -0
  198. package/components/identity.passkeys/operations/types/index.d.ts +2 -0
  199. package/components/identity.passkeys/operations/types/index.js +3 -0
  200. package/components/identity.passkeys/operations/types/index.js.map +1 -0
  201. package/components/identity.passkeys/operations/use.d.ts +16 -0
  202. package/components/identity.passkeys/operations/use.js +57 -0
  203. package/components/identity.passkeys/operations/use.js.map +1 -0
  204. package/components/identity.passkeys/source/authenticate.ts +48 -0
  205. package/components/identity.passkeys/source/challenge.ts +115 -0
  206. package/components/identity.passkeys/source/create.ts +77 -0
  207. package/components/identity.passkeys/source/delete.ts +15 -0
  208. package/components/identity.passkeys/source/lib/const.ts +1 -0
  209. package/components/identity.passkeys/source/list.ts +17 -0
  210. package/components/identity.passkeys/source/types/Configuration.ts +6 -0
  211. package/components/identity.passkeys/source/types/Context.ts +16 -0
  212. package/components/identity.passkeys/source/types/Passkey.ts +14 -0
  213. package/components/identity.passkeys/source/types/index.ts +2 -0
  214. package/components/identity.passkeys/source/use.ts +75 -0
  215. package/components/identity.passkeys/tsconfig.json +9 -0
  216. package/components/identity.roles/manifest.toa.yaml +4 -2
  217. package/components/identity.roles/operations/grant.js +2 -2
  218. package/components/identity.roles/operations/grant.js.map +1 -1
  219. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  220. package/components/identity.roles/receivers/identity.federation.principal.js +6 -0
  221. package/components/identity.roles/source/grant.ts +2 -2
  222. package/components/identity.tokens/manifest.toa.yaml +110 -13
  223. package/components/identity.tokens/operations/authenticate.d.ts +2 -2
  224. package/components/identity.tokens/operations/authenticate.js +13 -12
  225. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  226. package/components/identity.tokens/operations/decrypt.d.ts +15 -3
  227. package/components/identity.tokens/operations/decrypt.js +115 -20
  228. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  229. package/components/identity.tokens/operations/encrypt.d.ts +3 -3
  230. package/components/identity.tokens/operations/encrypt.js +30 -13
  231. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  232. package/components/identity.tokens/operations/issue.d.ts +24 -0
  233. package/components/identity.tokens/operations/issue.js +59 -0
  234. package/components/identity.tokens/operations/issue.js.map +1 -0
  235. package/components/identity.tokens/operations/lib/index.d.ts +3 -0
  236. package/components/identity.tokens/operations/lib/index.js +22 -0
  237. package/components/identity.tokens/operations/lib/index.js.map +1 -0
  238. package/components/identity.tokens/operations/lib/jose.d.ts +41 -0
  239. package/components/identity.tokens/operations/lib/jose.js +27 -0
  240. package/components/identity.tokens/operations/lib/jose.js.map +1 -0
  241. package/components/identity.tokens/operations/lib/key.d.ts +1 -0
  242. package/components/identity.tokens/operations/lib/key.js +11 -0
  243. package/components/identity.tokens/operations/lib/key.js.map +1 -0
  244. package/components/identity.tokens/operations/lib/pad.d.ts +1 -0
  245. package/components/identity.tokens/operations/lib/pad.js +5 -0
  246. package/components/identity.tokens/operations/lib/pad.js.map +1 -0
  247. package/components/identity.tokens/operations/lib/types.d.ts +84 -0
  248. package/components/identity.tokens/operations/lib/types.js.map +1 -0
  249. package/components/identity.tokens/operations/revoke.d.ts +2 -2
  250. package/components/identity.tokens/operations/revoke.js.map +1 -1
  251. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  252. package/components/identity.tokens/source/authenticate.test.ts +14 -7
  253. package/components/identity.tokens/source/authenticate.ts +15 -14
  254. package/components/identity.tokens/source/decrypt.test.ts +90 -16
  255. package/components/identity.tokens/source/decrypt.ts +152 -20
  256. package/components/identity.tokens/source/encrypt.test.ts +75 -13
  257. package/components/identity.tokens/source/encrypt.ts +42 -16
  258. package/components/identity.tokens/source/issue.ts +82 -0
  259. package/components/identity.tokens/source/lib/index.ts +3 -0
  260. package/components/identity.tokens/source/lib/jose.d.ts +1 -0
  261. package/components/identity.tokens/source/lib/jose.js +5 -0
  262. package/components/identity.tokens/source/lib/key.ts +8 -0
  263. package/components/identity.tokens/source/lib/pad.ts +1 -0
  264. package/components/identity.tokens/source/lib/paseto.test.ts +16 -0
  265. package/components/identity.tokens/source/lib/types.ts +97 -0
  266. package/components/identity.tokens/source/revoke.ts +2 -2
  267. package/{components/context.toa.yaml → context.toa.yaml} +6 -2
  268. package/cucumber.js +1 -1
  269. package/documentation/access.md +78 -27
  270. package/documentation/authorities.md +6 -11
  271. package/documentation/components.md +174 -56
  272. package/documentation/credentials.md +88 -0
  273. package/documentation/dev.md +30 -0
  274. package/documentation/flow.md +44 -0
  275. package/documentation/identity.md +125 -14
  276. package/documentation/introspection.md +82 -0
  277. package/documentation/io.md +73 -2
  278. package/documentation/map.md +115 -0
  279. package/documentation/notes/desync.jpg +0 -0
  280. package/documentation/notes/peers.md +59 -0
  281. package/documentation/notes/throttling.md +122 -0
  282. package/documentation/octets.md +122 -69
  283. package/documentation/passkeys.md +5 -0
  284. package/documentation/protocol.md +11 -4
  285. package/documentation/query.md +43 -0
  286. package/documentation/tracing.md +70 -0
  287. package/documentation/tree.md +13 -0
  288. package/features/access.feature +123 -3
  289. package/features/auth.assert.feature +57 -0
  290. package/features/auth.claims.feature +170 -0
  291. package/features/auth.incept.feature +120 -0
  292. package/features/auth.input.feature +59 -0
  293. package/features/authorities.feature +3 -3
  294. package/features/authorities.federation.feature +20 -20
  295. package/features/authorities.tokens.feature +1 -2
  296. package/features/body.feature +27 -0
  297. package/features/cache.feature +97 -8
  298. package/features/cors.feature +29 -8
  299. package/features/credentials.feature +106 -0
  300. package/features/dev.feature +87 -0
  301. package/features/dynamic.feature +82 -1
  302. package/features/errors.feature +17 -5
  303. package/features/etag.feature +223 -1
  304. package/features/flow.feature +148 -0
  305. package/features/identity.basic.feature +136 -7
  306. package/features/identity.feature +11 -4
  307. package/features/identity.federation.feature +210 -33
  308. package/features/identity.otp.feature +101 -0
  309. package/features/identity.roles.feature +53 -4
  310. package/features/identity.tokens.feature +4 -102
  311. package/features/identtiy.tokens.custom.feature +246 -0
  312. package/features/interruptions.feature +19 -0
  313. package/features/introspection.feature +153 -0
  314. package/features/introspection.map.feature +92 -0
  315. package/features/io.feature +0 -1
  316. package/features/io.throttle.feature +165 -0
  317. package/features/map.feature +357 -0
  318. package/features/methods.feature +47 -0
  319. package/features/octets.cloudinary.feature +226 -0
  320. package/features/octets.download.feature +190 -0
  321. package/features/octets.entries.feature +13 -61
  322. package/features/octets.feature +52 -70
  323. package/features/octets.head.feature +40 -0
  324. package/features/octets.location.feature +83 -0
  325. package/features/octets.meta.feature +63 -16
  326. package/features/octets.workflows.feature +333 -68
  327. package/features/passkeys.feature +66 -0
  328. package/features/probes.feature +1 -1
  329. package/features/query.feature +101 -0
  330. package/features/realtime.feature +34 -0
  331. package/features/response.feature +29 -0
  332. package/features/routes.feature +85 -0
  333. package/features/server.feature +21 -0
  334. package/features/steps/.env.example +5 -0
  335. package/features/steps/Captures.ts +12 -0
  336. package/features/steps/Common.ts +4 -0
  337. package/features/steps/Components.ts +14 -0
  338. package/features/steps/Database.ts +6 -2
  339. package/features/steps/Gateway.ts +51 -5
  340. package/features/steps/HTTP.ts +27 -3
  341. package/features/steps/IDP.ts +334 -0
  342. package/features/steps/Identity.ts +51 -0
  343. package/features/steps/OTP.ts +39 -0
  344. package/features/steps/Parameters.ts +94 -2
  345. package/features/steps/Realtime.ts +151 -0
  346. package/features/steps/Workspace.ts +1 -2
  347. package/features/steps/components/audit/manifest.toa.yaml +13 -0
  348. package/features/steps/components/audit/operations/record.js +9 -0
  349. package/features/steps/components/echo/manifest.toa.yaml +17 -0
  350. package/features/steps/components/echo/operations/echo.js +7 -0
  351. package/features/steps/components/echo/operations/parameters.js +7 -0
  352. package/features/steps/components/echo/operations/ping.js +7 -0
  353. package/features/steps/components/echo/operations/unwrap.js +7 -0
  354. package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
  355. package/features/steps/components/echo.beacon/operations/hello.js +5 -0
  356. package/features/steps/components/greeter/manifest.toa.yaml +0 -1
  357. package/features/steps/components/notify/manifest.toa.yaml +13 -0
  358. package/features/steps/components/notify/operations/send.js +9 -0
  359. package/features/steps/components/octets.tester/manifest.toa.yaml +26 -3
  360. package/features/steps/components/octets.tester/operations/authority.js +7 -0
  361. package/features/steps/components/octets.tester/operations/bar.js +0 -1
  362. package/features/steps/components/octets.tester/operations/baz.js +1 -1
  363. package/features/steps/components/octets.tester/operations/echo.js +1 -1
  364. package/features/steps/components/octets.tester/operations/foo.js +2 -2
  365. package/features/steps/components/octets.tester/operations/id.js +7 -0
  366. package/features/steps/components/octets.tester/operations/identity.js +7 -0
  367. package/features/steps/components/octets.tester/operations/redirect.js +12 -0
  368. package/features/steps/components/octets.tester/operations/yex.js +16 -0
  369. package/features/steps/components/octets.tester/operations/yield.js +13 -0
  370. package/features/steps/components/orders/manifest.toa.yaml +15 -0
  371. package/features/steps/components/orders/operations/create.js +9 -0
  372. package/features/steps/components/pots/manifest.toa.yaml +15 -4
  373. package/features/steps/components/pricing/manifest.toa.yaml +7 -0
  374. package/features/steps/components/pricing/operations/quote.js +7 -0
  375. package/features/steps/components/sequences/manifest.toa.yaml +0 -1
  376. package/features/steps/components/users/manifest.toa.yaml +4 -2
  377. package/features/steps/components/users/operations/create.js +15 -0
  378. package/features/steps/components/users.properties/manifest.toa.yaml +0 -1
  379. package/features/steps/map.ts +26 -0
  380. package/features/streams.feature +4 -0
  381. package/features/timestamps.feature +41 -0
  382. package/features/timing.feature +2 -22
  383. package/features/tracing.feature +123 -0
  384. package/package.json +35 -24
  385. package/readme.md +25 -1
  386. package/schemas/annotation.cos.yaml +12 -1
  387. package/schemas/io/throttle.cos.yaml +42 -0
  388. package/schemas/method.cos.yaml +2 -1
  389. package/schemas/node.cos.yaml +2 -0
  390. package/schemas/octets/put.cos.yaml +28 -0
  391. package/schemas/query.cos.yaml +7 -10
  392. package/schemas/querystring.cos.yaml +1 -0
  393. package/source/Annotation.ts +3 -1
  394. package/source/Branch.ts +1 -0
  395. package/source/Composition.ts +0 -6
  396. package/source/Context.ts +4 -1
  397. package/source/Directive.test.ts +80 -10
  398. package/source/Directive.ts +88 -15
  399. package/source/Endpoint.ts +113 -25
  400. package/source/Factory.ts +47 -3
  401. package/source/Gateway.ts +188 -13
  402. package/source/HTTP/Context.ts +65 -23
  403. package/source/HTTP/Server.ts +217 -48
  404. package/source/HTTP/Timing.ts +1 -12
  405. package/source/HTTP/exceptions.ts +38 -14
  406. package/source/HTTP/formats/index.ts +4 -5
  407. package/source/HTTP/formats/json.ts +2 -4
  408. package/source/HTTP/formats/msgpack.ts +0 -1
  409. package/source/HTTP/formats/text.ts +2 -4
  410. package/source/HTTP/formats/yaml.test.ts +9 -0
  411. package/source/HTTP/formats/yaml.ts +4 -4
  412. package/source/HTTP/messages.test.ts +70 -7
  413. package/source/HTTP/messages.ts +134 -19
  414. package/source/Interception.ts +8 -0
  415. package/source/Introspection.ts +11 -0
  416. package/source/Mapping.ts +63 -20
  417. package/source/Query.test.ts +3 -3
  418. package/source/Query.ts +107 -17
  419. package/source/RTD/Context.ts +4 -1
  420. package/source/RTD/Directives.ts +14 -1
  421. package/source/RTD/Endpoint.ts +3 -0
  422. package/source/RTD/Method.ts +16 -0
  423. package/source/RTD/Node.ts +65 -23
  424. package/source/RTD/Route.ts +19 -9
  425. package/source/RTD/Tree.ts +39 -9
  426. package/source/RTD/expiration.test.ts +78 -0
  427. package/source/RTD/factory.ts +30 -2
  428. package/source/RTD/segment.ts +2 -0
  429. package/source/RTD/syntax/parse.test.ts +1 -1
  430. package/source/RTD/syntax/parse.ts +37 -24
  431. package/source/RTD/syntax/types.ts +9 -4
  432. package/source/Remotes.test.ts +11 -3
  433. package/source/Remotes.ts +11 -7
  434. package/source/Tenant.ts +39 -12
  435. package/source/const.ts +1 -0
  436. package/source/deployment.ts +21 -13
  437. package/source/directives/auth/Anonymous.ts +3 -3
  438. package/source/directives/auth/Anyone.ts +13 -0
  439. package/source/directives/auth/Assert.ts +35 -0
  440. package/source/directives/auth/Authorization.ts +84 -22
  441. package/source/directives/auth/Delegate.ts +9 -5
  442. package/source/directives/auth/Echo.ts +16 -6
  443. package/source/directives/auth/Federation.ts +84 -0
  444. package/source/directives/auth/Id.ts +1 -1
  445. package/source/directives/auth/Incept.ts +75 -23
  446. package/source/directives/auth/Input.ts +71 -0
  447. package/source/directives/auth/Role.test.ts +2 -3
  448. package/source/directives/auth/Role.ts +6 -11
  449. package/source/directives/auth/Rule.ts +3 -6
  450. package/source/directives/auth/Scheme.ts +5 -5
  451. package/source/directives/auth/create.ts +11 -0
  452. package/source/directives/auth/schemes.ts +5 -2
  453. package/source/directives/auth/split.ts +1 -1
  454. package/source/directives/auth/types.ts +12 -7
  455. package/source/directives/cache/Cache.ts +20 -7
  456. package/source/directives/cache/Control.ts +16 -16
  457. package/source/directives/cors/CORS.ts +35 -18
  458. package/source/directives/dev/Development.ts +14 -7
  459. package/source/directives/dev/Faulty.ts +26 -0
  460. package/source/directives/dev/Sleep.ts +55 -0
  461. package/source/directives/dev/types.ts +1 -1
  462. package/source/directives/flow/Compose.ts +92 -0
  463. package/source/directives/flow/Fetch.ts +86 -0
  464. package/source/directives/flow/Flow.ts +42 -0
  465. package/source/directives/flow/index.ts +3 -0
  466. package/source/directives/flow/types.ts +7 -0
  467. package/source/directives/index.ts +3 -2
  468. package/source/directives/io/Directive.ts +9 -3
  469. package/source/directives/io/IO.ts +38 -10
  470. package/source/directives/io/Input.ts +17 -10
  471. package/source/directives/io/Output.ts +18 -9
  472. package/source/directives/io/Throttle.ts +31 -0
  473. package/source/directives/io/lib/throttle/Configuration.test.ts +60 -0
  474. package/source/directives/io/lib/throttle/Configuration.ts +63 -0
  475. package/source/directives/io/lib/throttle/Keys.ts +41 -0
  476. package/source/directives/io/lib/throttle/Quotas.test.ts +382 -0
  477. package/source/directives/io/lib/throttle/Quotas.ts +183 -0
  478. package/source/directives/io/lib/throttle/Sync.test.ts +153 -0
  479. package/source/directives/io/lib/throttle/Sync.ts +99 -0
  480. package/source/directives/io/lib/throttle/components/Component.ts +6 -0
  481. package/source/directives/io/lib/throttle/components/IP.ts +40 -0
  482. package/source/directives/io/lib/throttle/components/Identity.ts +19 -0
  483. package/source/directives/io/lib/throttle/components/Path.ts +8 -0
  484. package/source/directives/io/lib/throttle/components/Route.ts +19 -0
  485. package/source/directives/io/lib/throttle/components/Segment.ts +19 -0
  486. package/source/directives/io/lib/throttle/components/index.ts +19 -0
  487. package/source/directives/io/lib/throttle/conditions/Condition.ts +5 -0
  488. package/source/directives/io/lib/throttle/conditions/Status.ts +17 -0
  489. package/source/directives/io/lib/throttle/conditions/index.ts +11 -0
  490. package/source/directives/io/lib/throttle/index.ts +3 -0
  491. package/source/directives/io/schemas.test.ts +31 -0
  492. package/source/directives/io/schemas.ts +3 -0
  493. package/source/directives/map/Authority.ts +15 -0
  494. package/source/directives/map/Buffer.ts +15 -0
  495. package/source/directives/map/Claims.ts +58 -0
  496. package/source/directives/map/Directive.ts +4 -0
  497. package/source/directives/map/Headers.ts +38 -0
  498. package/source/directives/map/Language.ts +42 -0
  499. package/source/directives/map/Languages.ts +11 -0
  500. package/source/directives/map/Map.ts +63 -0
  501. package/source/directives/map/Mapping.ts +19 -0
  502. package/source/directives/{vary → map}/Properties.ts +2 -4
  503. package/source/directives/map/Segments.ts +33 -0
  504. package/source/directives/map/index.ts +3 -0
  505. package/source/directives/octets/Context.ts +3 -2
  506. package/source/directives/octets/Delete.ts +22 -19
  507. package/source/directives/octets/Get.ts +96 -0
  508. package/source/directives/octets/Octets.ts +11 -13
  509. package/source/directives/octets/Put.ts +138 -0
  510. package/source/directives/octets/Workflow.ts +9 -3
  511. package/source/directives/octets/bytes.test.ts +30 -0
  512. package/source/directives/octets/bytes.ts +18 -0
  513. package/source/directives/octets/schemas.ts +4 -8
  514. package/source/directives/octets/types.ts +2 -0
  515. package/source/directives/octets/workflows/Execution.ts +64 -8
  516. package/source/directives/octets/workflows/Workflow.ts +18 -7
  517. package/source/directives/octets/workflows/index.ts +1 -1
  518. package/source/exceptions.ts +16 -4
  519. package/source/manifest.ts +10 -11
  520. package/source/root.ts +16 -1
  521. package/transpiled/Annotation.d.ts +2 -1
  522. package/transpiled/Branch.d.ts +1 -0
  523. package/transpiled/Composition.d.ts +0 -1
  524. package/transpiled/Composition.js +0 -4
  525. package/transpiled/Composition.js.map +1 -1
  526. package/transpiled/Context.d.ts +2 -1
  527. package/transpiled/Directive.d.ts +8 -1
  528. package/transpiled/Directive.js +65 -14
  529. package/transpiled/Directive.js.map +1 -1
  530. package/transpiled/Endpoint.d.ts +8 -4
  531. package/transpiled/Endpoint.js +78 -19
  532. package/transpiled/Endpoint.js.map +1 -1
  533. package/transpiled/Factory.d.ts +1 -1
  534. package/transpiled/Factory.js +36 -2
  535. package/transpiled/Factory.js.map +1 -1
  536. package/transpiled/Gateway.d.ts +24 -0
  537. package/transpiled/Gateway.js +138 -13
  538. package/transpiled/Gateway.js.map +1 -1
  539. package/transpiled/HTTP/Context.d.ts +7 -3
  540. package/transpiled/HTTP/Context.js +51 -20
  541. package/transpiled/HTTP/Context.js.map +1 -1
  542. package/transpiled/HTTP/Server.d.ts +9 -4
  543. package/transpiled/HTTP/Server.js +170 -38
  544. package/transpiled/HTTP/Server.js.map +1 -1
  545. package/transpiled/HTTP/Timing.d.ts +0 -2
  546. package/transpiled/HTTP/Timing.js +0 -8
  547. package/transpiled/HTTP/Timing.js.map +1 -1
  548. package/transpiled/HTTP/exceptions.d.ts +21 -9
  549. package/transpiled/HTTP/exceptions.js +40 -18
  550. package/transpiled/HTTP/exceptions.js.map +1 -1
  551. package/transpiled/HTTP/formats/index.d.ts +2 -2
  552. package/transpiled/HTTP/formats/index.js +3 -3
  553. package/transpiled/HTTP/formats/index.js.map +1 -1
  554. package/transpiled/HTTP/formats/json.d.ts +2 -2
  555. package/transpiled/HTTP/formats/json.js +3 -4
  556. package/transpiled/HTTP/formats/json.js.map +1 -1
  557. package/transpiled/HTTP/formats/msgpack.d.ts +1 -1
  558. package/transpiled/HTTP/formats/msgpack.js.map +1 -1
  559. package/transpiled/HTTP/formats/text.d.ts +2 -2
  560. package/transpiled/HTTP/formats/text.js +3 -4
  561. package/transpiled/HTTP/formats/text.js.map +1 -1
  562. package/transpiled/HTTP/formats/yaml.d.ts +2 -2
  563. package/transpiled/HTTP/formats/yaml.js +5 -5
  564. package/transpiled/HTTP/formats/yaml.js.map +1 -1
  565. package/transpiled/HTTP/messages.d.ts +6 -1
  566. package/transpiled/HTTP/messages.js +118 -13
  567. package/transpiled/HTTP/messages.js.map +1 -1
  568. package/transpiled/Interception.d.ts +2 -0
  569. package/transpiled/Interception.js +4 -0
  570. package/transpiled/Interception.js.map +1 -1
  571. package/transpiled/Introspection.d.ts +9 -0
  572. package/transpiled/Introspection.js +3 -0
  573. package/transpiled/Introspection.js.map +1 -0
  574. package/transpiled/Mapping.d.ts +11 -2
  575. package/transpiled/Mapping.js +47 -18
  576. package/transpiled/Mapping.js.map +1 -1
  577. package/transpiled/Query.d.ts +11 -1
  578. package/transpiled/Query.js +78 -14
  579. package/transpiled/Query.js.map +1 -1
  580. package/transpiled/RTD/Context.d.ts +3 -1
  581. package/transpiled/RTD/Directives.d.ts +11 -1
  582. package/transpiled/RTD/Endpoint.d.ts +1 -0
  583. package/transpiled/RTD/Method.d.ts +4 -0
  584. package/transpiled/RTD/Method.js +11 -0
  585. package/transpiled/RTD/Method.js.map +1 -1
  586. package/transpiled/RTD/Node.d.ts +13 -2
  587. package/transpiled/RTD/Node.js +46 -17
  588. package/transpiled/RTD/Node.js.map +1 -1
  589. package/transpiled/RTD/Route.d.ts +5 -4
  590. package/transpiled/RTD/Route.js +10 -4
  591. package/transpiled/RTD/Route.js.map +1 -1
  592. package/transpiled/RTD/Tree.d.ts +8 -1
  593. package/transpiled/RTD/Tree.js +29 -3
  594. package/transpiled/RTD/Tree.js.map +1 -1
  595. package/transpiled/RTD/factory.d.ts +1 -0
  596. package/transpiled/RTD/factory.js +24 -3
  597. package/transpiled/RTD/factory.js.map +1 -1
  598. package/transpiled/RTD/segment.d.ts +1 -0
  599. package/transpiled/RTD/segment.js +2 -0
  600. package/transpiled/RTD/segment.js.map +1 -1
  601. package/transpiled/RTD/syntax/parse.js +34 -22
  602. package/transpiled/RTD/syntax/parse.js.map +1 -1
  603. package/transpiled/RTD/syntax/types.d.ts +8 -3
  604. package/transpiled/RTD/syntax/types.js +1 -1
  605. package/transpiled/RTD/syntax/types.js.map +1 -1
  606. package/transpiled/Remotes.d.ts +4 -4
  607. package/transpiled/Remotes.js +9 -6
  608. package/transpiled/Remotes.js.map +1 -1
  609. package/transpiled/Tenant.d.ts +9 -4
  610. package/transpiled/Tenant.js +26 -7
  611. package/transpiled/Tenant.js.map +1 -1
  612. package/transpiled/const.d.ts +1 -0
  613. package/transpiled/const.js +5 -0
  614. package/transpiled/const.js.map +1 -0
  615. package/transpiled/deployment.js +17 -11
  616. package/transpiled/deployment.js.map +1 -1
  617. package/transpiled/directives/auth/Anonymous.d.ts +2 -2
  618. package/transpiled/directives/auth/Anonymous.js +2 -2
  619. package/transpiled/directives/auth/Anonymous.js.map +1 -1
  620. package/transpiled/directives/auth/Anyone.d.ts +6 -0
  621. package/transpiled/directives/auth/Anyone.js +14 -0
  622. package/transpiled/directives/auth/Anyone.js.map +1 -0
  623. package/transpiled/directives/auth/Assert.d.ts +7 -0
  624. package/transpiled/directives/auth/Assert.js +57 -0
  625. package/transpiled/directives/auth/Assert.js.map +1 -0
  626. package/transpiled/directives/auth/Authorization.d.ts +5 -3
  627. package/transpiled/directives/auth/Authorization.js +67 -21
  628. package/transpiled/directives/auth/Authorization.js.map +1 -1
  629. package/transpiled/directives/auth/Delegate.d.ts +5 -4
  630. package/transpiled/directives/auth/Delegate.js +7 -3
  631. package/transpiled/directives/auth/Delegate.js.map +1 -1
  632. package/transpiled/directives/auth/Echo.d.ts +4 -4
  633. package/transpiled/directives/auth/Echo.js +11 -4
  634. package/transpiled/directives/auth/Echo.js.map +1 -1
  635. package/transpiled/directives/auth/Federation.d.ts +16 -0
  636. package/transpiled/directives/auth/Federation.js +57 -0
  637. package/transpiled/directives/auth/Federation.js.map +1 -0
  638. package/transpiled/directives/auth/Id.d.ts +1 -1
  639. package/transpiled/directives/auth/Id.js.map +1 -1
  640. package/transpiled/directives/auth/Incept.d.ts +8 -5
  641. package/transpiled/directives/auth/Incept.js +56 -18
  642. package/transpiled/directives/auth/Incept.js.map +1 -1
  643. package/transpiled/directives/auth/Input.d.ts +13 -0
  644. package/transpiled/directives/auth/Input.js +49 -0
  645. package/transpiled/directives/auth/Input.js.map +1 -0
  646. package/transpiled/directives/auth/Role.d.ts +1 -1
  647. package/transpiled/directives/auth/Role.js +4 -6
  648. package/transpiled/directives/auth/Role.js.map +1 -1
  649. package/transpiled/directives/auth/Rule.d.ts +2 -4
  650. package/transpiled/directives/auth/Rule.js +2 -2
  651. package/transpiled/directives/auth/Rule.js.map +1 -1
  652. package/transpiled/directives/auth/Scheme.d.ts +2 -2
  653. package/transpiled/directives/auth/Scheme.js +4 -4
  654. package/transpiled/directives/auth/Scheme.js.map +1 -1
  655. package/transpiled/directives/auth/create.d.ts +2 -0
  656. package/transpiled/directives/auth/create.js +14 -0
  657. package/transpiled/directives/auth/create.js.map +1 -0
  658. package/transpiled/directives/auth/schemes.d.ts +2 -1
  659. package/transpiled/directives/auth/schemes.js +5 -2
  660. package/transpiled/directives/auth/schemes.js.map +1 -1
  661. package/transpiled/directives/auth/split.js +1 -1
  662. package/transpiled/directives/auth/split.js.map +1 -1
  663. package/transpiled/directives/auth/types.d.ts +10 -7
  664. package/transpiled/directives/cache/Cache.d.ts +3 -3
  665. package/transpiled/directives/cache/Cache.js +15 -4
  666. package/transpiled/directives/cache/Cache.js.map +1 -1
  667. package/transpiled/directives/cache/Control.d.ts +2 -2
  668. package/transpiled/directives/cache/Control.js +12 -12
  669. package/transpiled/directives/cache/Control.js.map +1 -1
  670. package/transpiled/directives/cors/CORS.d.ts +8 -1
  671. package/transpiled/directives/cors/CORS.js +30 -16
  672. package/transpiled/directives/cors/CORS.js.map +1 -1
  673. package/transpiled/directives/dev/Development.d.ts +1 -1
  674. package/transpiled/directives/dev/Development.js +15 -7
  675. package/transpiled/directives/dev/Development.js.map +1 -1
  676. package/transpiled/directives/dev/Faulty.d.ts +8 -0
  677. package/transpiled/directives/dev/Faulty.js +26 -0
  678. package/transpiled/directives/dev/Faulty.js.map +1 -0
  679. package/transpiled/directives/dev/Sleep.d.ts +9 -0
  680. package/transpiled/directives/dev/Sleep.js +48 -0
  681. package/transpiled/directives/dev/Sleep.js.map +1 -0
  682. package/transpiled/directives/dev/types.d.ts +1 -1
  683. package/transpiled/directives/flow/Compose.d.ts +9 -0
  684. package/transpiled/directives/flow/Compose.js +94 -0
  685. package/transpiled/directives/flow/Compose.js.map +1 -0
  686. package/transpiled/directives/flow/Fetch.d.ts +12 -0
  687. package/transpiled/directives/flow/Fetch.js +58 -0
  688. package/transpiled/directives/flow/Fetch.js.map +1 -0
  689. package/transpiled/directives/flow/Flow.d.ts +10 -0
  690. package/transpiled/directives/flow/Flow.js +33 -0
  691. package/transpiled/directives/flow/Flow.js.map +1 -0
  692. package/transpiled/directives/flow/index.d.ts +2 -0
  693. package/transpiled/directives/flow/index.js +6 -0
  694. package/transpiled/directives/flow/index.js.map +1 -0
  695. package/transpiled/directives/flow/types.d.ts +6 -0
  696. package/transpiled/directives/flow/types.js.map +1 -0
  697. package/transpiled/directives/index.js +3 -2
  698. package/transpiled/directives/index.js.map +1 -1
  699. package/transpiled/directives/io/Directive.d.ts +8 -3
  700. package/transpiled/directives/io/IO.d.ts +14 -4
  701. package/transpiled/directives/io/IO.js +28 -7
  702. package/transpiled/directives/io/IO.js.map +1 -1
  703. package/transpiled/directives/io/Input.d.ts +2 -2
  704. package/transpiled/directives/io/Input.js +13 -7
  705. package/transpiled/directives/io/Input.js.map +1 -1
  706. package/transpiled/directives/io/Output.d.ts +3 -1
  707. package/transpiled/directives/io/Output.js +12 -6
  708. package/transpiled/directives/io/Output.js.map +1 -1
  709. package/transpiled/directives/io/Throttle.d.ts +11 -0
  710. package/transpiled/directives/io/Throttle.js +49 -0
  711. package/transpiled/directives/io/Throttle.js.map +1 -0
  712. package/transpiled/directives/io/lib/throttle/Configuration.d.ts +26 -0
  713. package/transpiled/directives/io/lib/throttle/Configuration.js +29 -0
  714. package/transpiled/directives/io/lib/throttle/Configuration.js.map +1 -0
  715. package/transpiled/directives/io/lib/throttle/Keys.d.ts +13 -0
  716. package/transpiled/directives/io/lib/throttle/Keys.js +31 -0
  717. package/transpiled/directives/io/lib/throttle/Keys.js.map +1 -0
  718. package/transpiled/directives/io/lib/throttle/Quotas.d.ts +69 -0
  719. package/transpiled/directives/io/lib/throttle/Quotas.js +138 -0
  720. package/transpiled/directives/io/lib/throttle/Quotas.js.map +1 -0
  721. package/transpiled/directives/io/lib/throttle/Sync.d.ts +30 -0
  722. package/transpiled/directives/io/lib/throttle/Sync.js +76 -0
  723. package/transpiled/directives/io/lib/throttle/Sync.js.map +1 -0
  724. package/transpiled/directives/io/lib/throttle/components/Component.d.ts +5 -0
  725. package/transpiled/directives/io/lib/throttle/components/Component.js +3 -0
  726. package/transpiled/directives/io/lib/throttle/components/Component.js.map +1 -0
  727. package/transpiled/directives/io/lib/throttle/components/IP.d.ts +6 -0
  728. package/transpiled/directives/io/lib/throttle/components/IP.js +33 -0
  729. package/transpiled/directives/io/lib/throttle/components/IP.js.map +1 -0
  730. package/transpiled/directives/io/lib/throttle/components/Identity.d.ts +11 -0
  731. package/transpiled/directives/io/lib/throttle/components/Identity.js +16 -0
  732. package/transpiled/directives/io/lib/throttle/components/Identity.js.map +1 -0
  733. package/transpiled/directives/io/lib/throttle/components/Path.d.ts +5 -0
  734. package/transpiled/directives/io/lib/throttle/components/Path.js +10 -0
  735. package/transpiled/directives/io/lib/throttle/components/Path.js.map +1 -0
  736. package/transpiled/directives/io/lib/throttle/components/Route.d.ts +12 -0
  737. package/transpiled/directives/io/lib/throttle/components/Route.js +20 -0
  738. package/transpiled/directives/io/lib/throttle/components/Route.js.map +1 -0
  739. package/transpiled/directives/io/lib/throttle/components/Segment.d.ts +9 -0
  740. package/transpiled/directives/io/lib/throttle/components/Segment.js +20 -0
  741. package/transpiled/directives/io/lib/throttle/components/Segment.js.map +1 -0
  742. package/transpiled/directives/io/lib/throttle/components/index.d.ts +5 -0
  743. package/transpiled/directives/io/lib/throttle/components/index.js +16 -0
  744. package/transpiled/directives/io/lib/throttle/components/index.js.map +1 -0
  745. package/transpiled/directives/io/lib/throttle/conditions/Condition.d.ts +4 -0
  746. package/transpiled/directives/io/lib/throttle/conditions/Condition.js +3 -0
  747. package/transpiled/directives/io/lib/throttle/conditions/Condition.js.map +1 -0
  748. package/transpiled/directives/io/lib/throttle/conditions/Status.d.ts +7 -0
  749. package/transpiled/directives/io/lib/throttle/conditions/Status.js +19 -0
  750. package/transpiled/directives/io/lib/throttle/conditions/Status.js.map +1 -0
  751. package/transpiled/directives/io/lib/throttle/conditions/index.d.ts +5 -0
  752. package/transpiled/directives/io/lib/throttle/conditions/index.js +8 -0
  753. package/transpiled/directives/io/lib/throttle/conditions/index.js.map +1 -0
  754. package/transpiled/directives/io/lib/throttle/index.d.ts +3 -0
  755. package/transpiled/directives/io/lib/throttle/index.js +10 -0
  756. package/transpiled/directives/io/lib/throttle/index.js.map +1 -0
  757. package/transpiled/directives/io/schemas.d.ts +2 -0
  758. package/transpiled/directives/io/schemas.js +2 -1
  759. package/transpiled/directives/io/schemas.js.map +1 -1
  760. package/transpiled/directives/map/Authority.d.ts +6 -0
  761. package/transpiled/directives/map/Authority.js +19 -0
  762. package/transpiled/directives/map/Authority.js.map +1 -0
  763. package/transpiled/directives/map/Buffer.d.ts +6 -0
  764. package/transpiled/directives/map/Buffer.js +19 -0
  765. package/transpiled/directives/map/Buffer.js.map +1 -0
  766. package/transpiled/directives/map/Claims.d.ts +10 -0
  767. package/transpiled/directives/map/Claims.js +44 -0
  768. package/transpiled/directives/map/Claims.js.map +1 -0
  769. package/transpiled/directives/map/Directive.d.ts +3 -0
  770. package/transpiled/directives/map/Directive.js.map +1 -0
  771. package/transpiled/directives/map/Headers.d.ts +7 -0
  772. package/transpiled/directives/map/Headers.js +34 -0
  773. package/transpiled/directives/map/Headers.js.map +1 -0
  774. package/transpiled/directives/map/Language.d.ts +10 -0
  775. package/transpiled/directives/map/Language.js +38 -0
  776. package/transpiled/directives/map/Language.js.map +1 -0
  777. package/transpiled/directives/map/Languages.d.ts +4 -0
  778. package/transpiled/directives/map/Languages.js +17 -0
  779. package/transpiled/directives/map/Languages.js.map +1 -0
  780. package/transpiled/directives/map/Map.d.ts +13 -0
  781. package/transpiled/directives/map/Map.js +48 -0
  782. package/transpiled/directives/map/Map.js.map +1 -0
  783. package/transpiled/directives/map/Mapping.d.ts +13 -0
  784. package/transpiled/directives/map/Mapping.js +13 -0
  785. package/transpiled/directives/map/Mapping.js.map +1 -0
  786. package/transpiled/directives/{vary → map}/Properties.d.ts +2 -2
  787. package/transpiled/directives/{vary → map}/Properties.js +1 -3
  788. package/transpiled/directives/map/Properties.js.map +1 -0
  789. package/transpiled/directives/map/Segments.d.ts +6 -0
  790. package/transpiled/directives/map/Segments.js +30 -0
  791. package/transpiled/directives/map/Segments.js.map +1 -0
  792. package/transpiled/directives/map/index.d.ts +2 -0
  793. package/transpiled/directives/map/index.js +6 -0
  794. package/transpiled/directives/map/index.js.map +1 -0
  795. package/transpiled/directives/octets/Context.js +4 -24
  796. package/transpiled/directives/octets/Context.js.map +1 -1
  797. package/transpiled/directives/octets/Delete.js +15 -12
  798. package/transpiled/directives/octets/Delete.js.map +1 -1
  799. package/transpiled/directives/octets/{Fetch.d.ts → Get.d.ts} +5 -6
  800. package/transpiled/directives/octets/{Fetch.js → Get.js} +34 -30
  801. package/transpiled/directives/octets/Get.js.map +1 -0
  802. package/transpiled/directives/octets/Octets.js +10 -11
  803. package/transpiled/directives/octets/Octets.js.map +1 -1
  804. package/transpiled/directives/octets/{Store.d.ts → Put.d.ts} +8 -2
  805. package/transpiled/directives/octets/{Store.js → Put.js} +33 -27
  806. package/transpiled/directives/octets/Put.js.map +1 -0
  807. package/transpiled/directives/octets/Workflow.js +7 -2
  808. package/transpiled/directives/octets/Workflow.js.map +1 -1
  809. package/transpiled/directives/octets/bytes.d.ts +1 -0
  810. package/transpiled/directives/octets/bytes.js +21 -0
  811. package/transpiled/directives/octets/bytes.js.map +1 -0
  812. package/transpiled/directives/octets/schemas.d.ts +4 -8
  813. package/transpiled/directives/octets/schemas.js +3 -6
  814. package/transpiled/directives/octets/schemas.js.map +1 -1
  815. package/transpiled/directives/octets/types.d.ts +2 -0
  816. package/transpiled/directives/octets/workflows/Execution.d.ts +7 -1
  817. package/transpiled/directives/octets/workflows/Execution.js +46 -9
  818. package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
  819. package/transpiled/directives/octets/workflows/Workflow.d.ts +8 -3
  820. package/transpiled/directives/octets/workflows/Workflow.js +10 -4
  821. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  822. package/transpiled/directives/octets/workflows/index.d.ts +1 -1
  823. package/transpiled/directives/octets/workflows/index.js.map +1 -1
  824. package/transpiled/exceptions.js +11 -2
  825. package/transpiled/exceptions.js.map +1 -1
  826. package/transpiled/manifest.js +10 -11
  827. package/transpiled/manifest.js.map +1 -1
  828. package/transpiled/root.js +16 -1
  829. package/transpiled/root.js.map +1 -1
  830. package/transpiled/tsconfig.tsbuildinfo +1 -1
  831. package/components/identity.federation/operations/lib/assertions-as-values.d.ts +0 -4
  832. package/components/identity.federation/operations/lib/assertions-as-values.js.map +0 -1
  833. package/components/identity.federation/operations/lib/jwt.d.ts +0 -20
  834. package/components/identity.federation/operations/lib/jwt.js +0 -136
  835. package/components/identity.federation/operations/lib/jwt.js.map +0 -1
  836. package/components/identity.federation/operations/schemas.d.ts +0 -63
  837. package/components/identity.federation/operations/schemas.js +0 -9
  838. package/components/identity.federation/operations/schemas.js.map +0 -1
  839. package/components/identity.federation/operations/types.d.ts +0 -56
  840. package/components/identity.federation/operations/types.js.map +0 -1
  841. package/components/identity.federation/source/lib/assertions-as-values.ts +0 -19
  842. package/components/identity.federation/source/lib/jwt.test.ts +0 -56
  843. package/components/identity.federation/source/lib/jwt.ts +0 -171
  844. package/components/identity.federation/source/schemas.ts +0 -65
  845. package/components/identity.federation/source/types.ts +0 -62
  846. package/components/identity.tokens/operations/types.d.ts +0 -46
  847. package/components/identity.tokens/operations/types.js.map +0 -1
  848. package/components/identity.tokens/source/types.ts +0 -55
  849. package/components/octets.storage/manifest.toa.yaml +0 -21
  850. package/components/octets.storage/operations/fetch.js +0 -46
  851. package/components/octets.storage/operations/get.js +0 -7
  852. package/components/octets.storage/operations/list.js +0 -7
  853. package/components/octets.storage/operations/store.js +0 -11
  854. package/documentation/vary.md +0 -69
  855. package/features/steps/IdP.ts +0 -154
  856. package/features/steps/components/octets.tester/operations/diversify.js +0 -14
  857. package/features/vary.feature +0 -252
  858. package/schemas/octets/context.cos.yaml +0 -1
  859. package/schemas/octets/fetch.cos.yaml +0 -3
  860. package/schemas/octets/permute.cos.yaml +0 -1
  861. package/schemas/octets/store.cos.yaml +0 -3
  862. package/source/directives/octets/Fetch.ts +0 -100
  863. package/source/directives/octets/List.ts +0 -72
  864. package/source/directives/octets/Store.ts +0 -126
  865. package/source/directives/vary/Directive.ts +0 -7
  866. package/source/directives/vary/Embed.ts +0 -68
  867. package/source/directives/vary/Vary.ts +0 -50
  868. package/source/directives/vary/embeddings/Authority.ts +0 -8
  869. package/source/directives/vary/embeddings/Embedding.ts +0 -7
  870. package/source/directives/vary/embeddings/Header.ts +0 -32
  871. package/source/directives/vary/embeddings/Language.ts +0 -31
  872. package/source/directives/vary/embeddings/Parameter.ts +0 -14
  873. package/source/directives/vary/embeddings/index.ts +0 -13
  874. package/source/directives/vary/index.ts +0 -3
  875. package/transpiled/directives/octets/Fetch.js.map +0 -1
  876. package/transpiled/directives/octets/List.d.ts +0 -16
  877. package/transpiled/directives/octets/List.js +0 -74
  878. package/transpiled/directives/octets/List.js.map +0 -1
  879. package/transpiled/directives/octets/Store.js.map +0 -1
  880. package/transpiled/directives/vary/Directive.d.ts +0 -6
  881. package/transpiled/directives/vary/Directive.js.map +0 -1
  882. package/transpiled/directives/vary/Embed.d.ts +0 -11
  883. package/transpiled/directives/vary/Embed.js +0 -51
  884. package/transpiled/directives/vary/Embed.js.map +0 -1
  885. package/transpiled/directives/vary/Properties.js.map +0 -1
  886. package/transpiled/directives/vary/Vary.d.ts +0 -10
  887. package/transpiled/directives/vary/Vary.js +0 -36
  888. package/transpiled/directives/vary/Vary.js.map +0 -1
  889. package/transpiled/directives/vary/embeddings/Authority.d.ts +0 -5
  890. package/transpiled/directives/vary/embeddings/Authority.js +0 -10
  891. package/transpiled/directives/vary/embeddings/Authority.js.map +0 -1
  892. package/transpiled/directives/vary/embeddings/Embedding.d.ts +0 -6
  893. package/transpiled/directives/vary/embeddings/Embedding.js.map +0 -1
  894. package/transpiled/directives/vary/embeddings/Header.d.ts +0 -7
  895. package/transpiled/directives/vary/embeddings/Header.js +0 -28
  896. package/transpiled/directives/vary/embeddings/Header.js.map +0 -1
  897. package/transpiled/directives/vary/embeddings/Language.d.ts +0 -7
  898. package/transpiled/directives/vary/embeddings/Language.js +0 -28
  899. package/transpiled/directives/vary/embeddings/Language.js.map +0 -1
  900. package/transpiled/directives/vary/embeddings/Parameter.d.ts +0 -7
  901. package/transpiled/directives/vary/embeddings/Parameter.js +0 -14
  902. package/transpiled/directives/vary/embeddings/Parameter.js.map +0 -1
  903. package/transpiled/directives/vary/embeddings/index.d.ts +0 -5
  904. package/transpiled/directives/vary/embeddings/index.js +0 -14
  905. package/transpiled/directives/vary/embeddings/index.js.map +0 -1
  906. package/transpiled/directives/vary/index.d.ts +0 -2
  907. package/transpiled/directives/vary/index.js +0 -6
  908. package/transpiled/directives/vary/index.js.map +0 -1
  909. /package/components/{octets.storage → exposition.octets}/operations/delete.js +0 -0
  910. /package/components/{identity.federation/operations → identity.tokens/operations/lib}/types.js +0 -0
  911. /package/schemas/octets/{list.cos.yaml → get.cos.yaml} +0 -0
  912. /package/{components/identity.tokens/operations → transpiled/directives/flow}/types.js +0 -0
  913. /package/transpiled/directives/{vary → map}/Directive.js +0 -0
@@ -1,17 +1,20 @@
1
- import { type Component } from '@toa.io/core'
2
- import { type Remotes } from './Remotes'
1
+ import { Readable } from 'node:stream'
2
+ import { console } from 'openspan'
3
3
  import { Mapping } from './Mapping'
4
- import { type Context } from './Context'
5
4
  import * as http from './HTTP'
5
+ import type { Introspection, Schema } from './Introspection'
6
+ import type { Remote } from '@toa.io/core'
7
+ import type { Remotes } from './Remotes'
8
+ import type { Context } from './Context'
6
9
  import type * as RTD from './RTD'
7
10
 
8
11
  export class Endpoint implements RTD.Endpoint {
9
12
  private readonly endpoint: string
10
13
  private readonly mapping: Mapping
11
- private readonly discovery: Promise<Component>
12
- private remote: Component | null = null
14
+ private readonly discovery: Promise<Remote>
15
+ private remote: Remote | null = null
13
16
 
14
- public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Component>) {
17
+ public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Remote>) {
15
18
  this.endpoint = endpoint
16
19
  this.mapping = mapping
17
20
  this.discovery = discovery
@@ -24,28 +27,34 @@ export class Endpoint implements RTD.Endpoint {
24
27
 
25
28
  this.remote ??= await this.discovery
26
29
 
30
+ const endpoint = this.remote.locator.id + '.' + this.endpoint
31
+
32
+ console.debug('Calling operation', { endpoint, request })
33
+
27
34
  const reply = await this.remote.invoke(this.endpoint, request)
28
35
 
29
- if (context.debug)
30
- console.debug('Call', `${this.remote.locator.id}.${this.endpoint}`, request)
36
+ console.debug('Received reply', { endpoint, reply: reply instanceof Readable ? '[Readable stream]' : reply })
31
37
 
32
38
  if (reply instanceof Error)
33
39
  throw new http.UnprocessableEntity(reply)
34
40
 
35
41
  const message: http.OutgoingMessage = {}
36
42
 
37
- if (typeof reply === 'object' && reply !== null && '_version' in reply) {
43
+ // etag
44
+ if (reply !== null && reply !== undefined) {
38
45
  const etag = context.request.headers['if-none-match']
39
46
 
40
- message.headers ??= new Headers()
47
+ if (this.conditionalGet(reply, etag, message))
48
+ return message
49
+ }
41
50
 
42
- if (etag !== undefined && reply._version === this.version(etag)) {
43
- message.status = 304
44
- message.headers.set('etag', etag)
51
+ // last-modified
52
+ if (typeof reply === 'object' && reply !== null && ('_updated' in reply || '_created' in reply)) {
53
+ const timestamp: string = reply._updated ?? reply._created
54
+ const date = new Date(timestamp)
45
55
 
46
- return message
47
- } else
48
- message.headers.set('etag', `"${reply._version.toString()}"`)
56
+ message.headers ??= new Headers()
57
+ message.headers.set('last-modified', date.toUTCString())
49
58
  }
50
59
 
51
60
  message.body = reply
@@ -53,30 +62,106 @@ export class Endpoint implements RTD.Endpoint {
53
62
  return message
54
63
  }
55
64
 
65
+ public async explain (parameters: RTD.Parameter[]): Promise<Introspection> {
66
+ this.remote ??= await this.discovery
67
+
68
+ const operation = await this.remote.explain(this.endpoint)
69
+
70
+ let route: Record<string, Schema> | null = null
71
+
72
+ if (operation.input?.type === 'object')
73
+ for (const parameter of parameters) {
74
+ const schema = operation.input.properties[parameter.name]
75
+
76
+ // eslint-disable-next-line max-depth
77
+ if (schema !== undefined) {
78
+ route ??= {}
79
+ route[parameter.name] = schema
80
+
81
+ delete operation.input.properties[parameter.name]
82
+ }
83
+ }
84
+
85
+ const query = this.mapping.explain(operation)
86
+ const introspection: Introspection = {}
87
+
88
+ if (route !== null)
89
+ introspection.route = route
90
+
91
+ if (query !== null)
92
+ introspection.query = query
93
+
94
+ Object.assign(introspection, operation)
95
+
96
+ return introspection
97
+ }
98
+
56
99
  public async close (): Promise<void> {
57
100
  this.remote ??= await this.discovery
58
101
 
59
102
  await this.remote.disconnect(INTERRUPT)
60
103
  }
61
104
 
105
+ private conditionalGet (reply: unknown, etag: string | undefined, message: http.OutgoingMessage): boolean {
106
+ message.headers ??= new Headers()
107
+
108
+ if (typeof reply === 'object' && reply !== null && '_version' in reply) {
109
+ const version = reply._version as number
110
+ const matched = etag === undefined ? null : this.matchVersion(etag)
111
+
112
+ if (etag !== undefined && matched !== null && version === matched) {
113
+ message.status = 304
114
+ message.headers.set('etag', etag)
115
+
116
+ return true
117
+ }
118
+
119
+ message.headers.set('etag', `"${version.toString()}"`)
120
+
121
+ return false
122
+ }
123
+
124
+ if (reply instanceof Readable)
125
+ return false
126
+
127
+ /*
128
+ * A reply that carries no version is tagged with a hash of its body. The body is
129
+ * serialized anyway when the response is written, so the tag is computed from what
130
+ * is actually sent rather than from a second serialization of the reply — which
131
+ * makes it specific to the negotiated representation, hence `vary: accept`.
132
+ */
133
+ message.etag = true
134
+
135
+ return false
136
+ }
137
+
62
138
  private query (context: http.Context): http.Query {
63
139
  const query: http.Query = Object.fromEntries(context.url.searchParams)
64
140
  const etag = context.request.headers['if-match']
65
141
 
66
- if (etag !== undefined)
142
+ if (etag !== undefined && this.mapping.queryable)
67
143
  query.version = this.version(etag)
68
144
 
69
145
  return query
70
146
  }
71
147
 
72
- private version (etag: string): number {
148
+ private matchVersion (etag: string): number | null {
73
149
  const match = etag.match(ETAG)
74
150
 
75
151
  if (match === null)
76
- throw new http.BadRequest('Invalid ETag.')
152
+ return null
77
153
 
78
154
  return Number.parseInt(match.groups!.version)
79
155
  }
156
+
157
+ private version (etag: string): number {
158
+ const version = this.matchVersion(etag)
159
+
160
+ if (version === null)
161
+ throw new http.BadRequest('Invalid ETag')
162
+
163
+ return version
164
+ }
80
165
  }
81
166
 
82
167
  export class EndpointsFactory implements RTD.EndpointsFactory {
@@ -88,21 +173,24 @@ export class EndpointsFactory implements RTD.EndpointsFactory {
88
173
 
89
174
  public create (method: RTD.syntax.Method, context: Context): Endpoint {
90
175
  if (method.mapping === undefined)
91
- throw new Error('Cannot create Endpoint without mapping.')
176
+ throw new Error('Cannot create Endpoint without mapping')
92
177
 
93
178
  const mapping = Mapping.create(method.mapping.query)
94
- const namespace = method.mapping.namespace ?? context.extension?.namespace
95
- const component = method.mapping.component ?? context.extension?.component
179
+
180
+ const branch = context.extension
181
+
182
+ const namespace = method.mapping.namespace ?? branch?.namespace
183
+ const component = method.mapping.component ?? branch?.component
96
184
 
97
185
  if (namespace === undefined || component === undefined)
98
- throw new Error('Annotation endpoints must be fully qualified.')
186
+ throw new Error('Annotation endpoints must be fully qualified')
99
187
 
100
- const discovery = this.remotes.discover(namespace, component)
188
+ const discovery = this.remotes.discover(namespace, component, branch?.version)
101
189
 
102
190
  return new Endpoint(method.mapping.endpoint, mapping, discovery)
103
191
  }
104
192
  }
105
193
 
106
- const ETAG = /^"(?<version>\d{1,32})"$/
194
+ const ETAG = /^(W\/)?"(?<version>\d{1,32})"$/
107
195
 
108
196
  const INTERRUPT = true
package/source/Factory.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import assert from 'node:assert'
2
+ import { createHash } from 'node:crypto'
3
+ import { console, traces, type LevelName, type TracesOptions } from 'openspan'
2
4
  import { decode } from '@toa.io/generic'
3
5
  import { Tenant } from './Tenant'
4
6
  import { Gateway } from './Gateway'
5
7
  import { Remotes } from './Remotes'
6
- import { Tree, syntax } from './RTD'
8
+ import { Tree } from './RTD'
7
9
  import { EndpointsFactory } from './Endpoint'
8
10
  import { families, interceptors } from './directives'
9
11
  import { DirectivesFactory } from './Directive'
@@ -11,6 +13,8 @@ import { Composition } from './Composition'
11
13
  import * as root from './root'
12
14
  import { Interception } from './Interception'
13
15
  import * as http from './HTTP'
16
+ import type { Branch } from './Branch'
17
+ import type { syntax } from './RTD'
14
18
  import type { Broadcast } from './Gateway'
15
19
  import type { Connector, Locator, extensions } from '@toa.io/core'
16
20
 
@@ -23,17 +27,28 @@ export class Factory implements extensions.Factory {
23
27
 
24
28
  public tenant (locator: Locator, node: syntax.Node): Connector {
25
29
  const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL, locator.id)
30
+ const hash = createHash('sha256').update(JSON.stringify(node)).digest('hex')
26
31
 
27
- return new Tenant(broadcast, locator, node)
32
+ const branch: Branch = {
33
+ namespace: locator.namespace,
34
+ component: locator.name,
35
+ isolated: locator.namespace === 'identity',
36
+ node,
37
+ version: hash
38
+ }
39
+
40
+ return new Tenant(broadcast, branch)
28
41
  }
29
42
 
30
43
  public service (): Connector | null {
31
44
  assert.ok(process.env.TOA_EXPOSITION_PROPERTIES,
32
45
  'TOA_EXPOSITION_PROPERTIES is undefined')
33
46
 
47
+ configureLogs()
48
+
34
49
  const options = decode<http.Options>(process.env.TOA_EXPOSITION_PROPERTIES)
35
50
  const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
36
- const server = http.Server.create({ ...options, methods: syntax.verbs })
51
+ const server = http.Server.create({ ...options })
37
52
  const remotes = new Remotes(this.boot)
38
53
  const node = root.resolve()
39
54
  const methods = new EndpointsFactory(remotes)
@@ -55,6 +70,35 @@ export class Factory implements extensions.Factory {
55
70
  }
56
71
 
57
72
  const CHANNEL = 'exposition'
73
+ const LOGS_PREFIX = 'TOA_TELEMETRY_LOGS'
74
+ const TRACES_ENV = 'TOA_TELEMETRY_TRACES'
75
+
76
+ function configureLogs (): void {
77
+ const globEnv = process.env[LOGS_PREFIX]
78
+ const level: LevelName = process.env.TOA_DEV === '1' ? 'trace' : 'info'
79
+ const options = globEnv === undefined ? { level } : decode<{ level?: LevelName }>(globEnv)
80
+
81
+ console.configure({ level: options.level ?? level })
82
+
83
+ const tracesEnv = process.env[TRACES_ENV]
84
+
85
+ traces(tracesEnv === undefined ? development() : decode<TracesOptions>(tracesEnv))
86
+ }
87
+
88
+ /**
89
+ * Tracing is off unless it is configured. The console exporter is a local development
90
+ * mechanism, so it is turned on for `toa dev` and for a boot trace the CLI has already
91
+ * asked for (`runtime/boot/src/span.js`), and nowhere else — a deployment that wants
92
+ * traces annotates `telemetry.traces.exporters`.
93
+ *
94
+ * The gateway boots without the telemetry extension, hence the copy of
95
+ * `extensions/telemetry/source/extension.ts`.
96
+ */
97
+ function development (): TracesOptions {
98
+ const local = process.env.TOA_DEV === '1' || process.env.TOA_BOOT_TRACE === '1'
99
+
100
+ return local ? { exporters: { console: {} } } : {}
101
+ }
58
102
 
59
103
  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
60
104
  export type Bootloader = typeof import('@toa.io/boot')
package/source/Gateway.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import assert from 'node:assert'
2
+ import { setTimeout } from 'node:timers/promises'
3
+ import { console } from 'openspan'
1
4
  import { type bindings, Connector } from '@toa.io/core'
2
5
  import * as http from './HTTP'
3
6
  import { rethrow } from './exceptions'
4
7
  import type { Interception } from './Interception'
5
- import type { Method, Parameter, Tree } from './RTD'
8
+ import type { Method, Node, Parameter, Tree, Match } from './RTD'
6
9
  import type { Label } from './discovery'
7
10
  import type { Branch } from './Branch'
8
11
 
@@ -10,6 +13,12 @@ export class Gateway extends Connector {
10
13
  private readonly broadcast: Broadcast
11
14
  private readonly tree: Tree
12
15
  private readonly interceptor: Interception
16
+ private readonly branches = new Map<string, Exposed>()
17
+ private lastMerge = 0
18
+ private widestGap = 0
19
+ private lastPing = 0
20
+ private stopped = false
21
+ private resolveFirstMerge: (() => void) | null = null
13
22
 
14
23
  public constructor (broadcast: Broadcast, tree: Tree, interception: Interception) {
15
24
  super()
@@ -28,17 +37,20 @@ export class Gateway extends Connector {
28
37
  if (interception !== null)
29
38
  return interception
30
39
 
31
- const match = this.tree.match(context.url.pathname)
40
+ const { node, parameters } = this.match(context)
32
41
 
33
- if (match === null)
34
- throw new http.NotFound('Route not found')
42
+ if (context.request.method === 'OPTIONS')
43
+ return await this.explain(node, parameters)
44
+
45
+ let verb = context.request.method
35
46
 
36
- const { node, parameters } = match
47
+ if (!(verb in node.methods) && verb === 'HEAD' && 'GET' in node.methods)
48
+ verb = 'GET'
37
49
 
38
- if (!(context.request.method in node.methods))
50
+ if (!(verb in node.methods))
39
51
  throw new http.MethodNotAllowed()
40
52
 
41
- const method = node.methods[context.request.method]
53
+ const method = node.methods[verb]
42
54
 
43
55
  const interruption = await context.timing.capture('preflight',
44
56
  method.directives.preflight(context, parameters)).catch(rethrow)
@@ -55,13 +67,46 @@ export class Gateway extends Connector {
55
67
  protected override async open (): Promise<void> {
56
68
  await this.discover()
57
69
 
58
- console.info('Gateway has started and is awaiting resource branches')
70
+ console.info('Gateway started')
59
71
  }
60
72
 
61
73
  protected override dispose (): void {
74
+ this.stopped = true
75
+
76
+ this.tree.dispose()
77
+
62
78
  console.info('Gateway is closed')
63
79
  }
64
80
 
81
+ private match (context: http.Context): Match {
82
+ const match = this.tree.match(context.url.pathname)
83
+
84
+ if (match === null) {
85
+ // the route may be missing because an expose has been lost
86
+ this.reping()
87
+
88
+ throw new http.NotFound('Route not found')
89
+ }
90
+
91
+ if (match.node.forward === null)
92
+ return match
93
+
94
+ const destination = match.node.forward.replace(/\/:([^/]+)/g,
95
+ (_, name) => {
96
+ const value = match.parameters.find((parameter) => parameter.name === name)?.value
97
+
98
+ assert.ok(value !== undefined, `Forwarded parameter '${name}' not found`)
99
+
100
+ return `/${value}`
101
+ })
102
+
103
+ const forward = this.tree.match(destination)
104
+
105
+ assert.ok(forward !== null, 'Forwarded route not found')
106
+
107
+ return forward
108
+ }
109
+
65
110
  private async call (method: Method, context: http.Context, parameters: Parameter[]): Promise<http.OutgoingMessage> {
66
111
  if (context.url.pathname[context.url.pathname.length - 1] !== '/')
67
112
  throw new http.NotFound('Trailing slash is required')
@@ -77,21 +122,151 @@ export class Gateway extends Connector {
77
122
  .catch(rethrow) as http.OutgoingMessage
78
123
  }
79
124
 
125
+ private async explain (node: Node, parameters: Parameter[]): Promise<http.OutgoingMessage> {
126
+ const body = await node.explain(parameters)
127
+ const allow = [...Object.keys(node.methods)].join(', ')
128
+ const headers = new Headers({ allow })
129
+
130
+ return { body, headers }
131
+ }
132
+
80
133
  private async discover (): Promise<void> {
134
+ const first = new Promise<void>((resolve) => {
135
+ this.resolveFirstMerge = resolve
136
+ })
137
+
81
138
  await this.broadcast.receive<Branch>('expose', this.merge.bind(this))
139
+
140
+ void this.knock()
141
+
142
+ await this.settled(first)
143
+ }
144
+
145
+ /**
146
+ * A single ping is enough only if every tenant is listening by then, which is
147
+ * not the case while the deployment is still rolling out.
148
+ */
149
+ private async knock (): Promise<void> {
150
+ for (const delay of KNOCK_DELAYS) {
151
+ if (this.stopped)
152
+ return
153
+
154
+ if (delay > 0)
155
+ await setTimeout(delay, undefined, { ref: false })
156
+
157
+ await this.ping()
158
+ }
159
+ }
160
+
161
+ private async ping (): Promise<void> {
162
+ if (this.stopped)
163
+ return
164
+
165
+ this.lastPing = Date.now()
166
+
82
167
  await this.broadcast.transmit<null>('ping', null)
168
+ .catch((exception: Error) => console.error('Discovery ping failed',
169
+ { message: exception.message }))
170
+ }
171
+
172
+ private reping (): void {
173
+ if (Date.now() - this.lastPing < PING_COOLDOWN)
174
+ return
175
+
176
+ void this.ping()
177
+ }
178
+
179
+ private async settled (first: Promise<void>): Promise<void> {
180
+ const deadline = Date.now() + SETTLE_TIMEOUT
181
+ const abort = new AbortController()
182
+
183
+ // an uncancelled timer keeps the process alive long after the race is won
184
+ await Promise.race([first, setTimeout(SETTLE_TIMEOUT, undefined, { signal: abort.signal })])
185
+ .finally(() => { abort.abort() })
186
+ .catch(() => {})
187
+
188
+ if (this.lastMerge === 0) {
189
+ console.warn('Discovery timed out waiting for the first expose')
190
+
191
+ return
192
+ }
193
+
194
+ while (Date.now() - this.lastMerge < this.quiet()) {
195
+ if (Date.now() >= deadline)
196
+ break
197
+
198
+ await setTimeout(SETTLE_POLL)
199
+ }
200
+ }
201
+
202
+ /**
203
+ * How long the branches must stay quiet before discovery counts as settled.
204
+ *
205
+ * Every tenant of a local composition answers the first ping at once, so a short window
206
+ * is enough; a rolling deployment brings them up seconds apart, and the window grows with
207
+ * the widest gap seen so far to keep waiting for the ones still starting.
208
+ */
209
+ private quiet (): number {
210
+ const adaptive = this.widestGap * SETTLE_QUIET_FACTOR
211
+
212
+ return Math.min(Math.max(adaptive, SETTLE_QUIET_MIN), SETTLE_QUIET_MAX)
83
213
  }
84
214
 
85
215
  private merge (branch: Branch): void {
216
+ const id = branch.namespace + '.' + branch.component
217
+
218
+ const attributes = {
219
+ namespace: branch.namespace,
220
+ component: branch.component,
221
+ version: branch.version
222
+ }
223
+
224
+ const exposed = this.branches.get(id)
225
+
226
+ // rebuilding an identical branch would only tear down its live endpoints
227
+ if (exposed?.version === branch.version) {
228
+ this.tree.refresh(exposed.nodes)
229
+ console.debug('Branch refreshed', attributes)
230
+
231
+ return
232
+ }
233
+
234
+ let nodes: Node[]
235
+
86
236
  try {
87
- this.tree.merge(branch.node, branch)
237
+ nodes = this.tree.merge(branch.node, branch)
238
+ } catch (exception: unknown) {
239
+ const message = exception instanceof Error ? exception.message : 'Unknown error'
88
240
 
89
- console.info('Resource branch of ' +
90
- `'${branch.namespace}.${branch.component}' has been merged`)
91
- } catch (exception) {
92
- console.error(exception)
241
+ console.error('Branch merge exception', { message, ...attributes })
242
+
243
+ return
93
244
  }
245
+
246
+ this.branches.set(id, { version: branch.version, nodes })
247
+
248
+ if (this.lastMerge !== 0)
249
+ this.widestGap = Math.max(this.widestGap, Date.now() - this.lastMerge)
250
+
251
+ this.lastMerge = Date.now()
252
+ this.resolveFirstMerge?.()
253
+ this.resolveFirstMerge = null
254
+
255
+ console.info('Branch merged', attributes)
94
256
  }
95
257
  }
96
258
 
97
259
  export type Broadcast = bindings.Broadcast<Label>
260
+
261
+ interface Exposed {
262
+ version: string
263
+ nodes: Node[]
264
+ }
265
+
266
+ const SETTLE_QUIET_MIN = 500
267
+ const SETTLE_QUIET_MAX = 10_000
268
+ const SETTLE_QUIET_FACTOR = 2
269
+ const SETTLE_TIMEOUT = 30_000
270
+ const SETTLE_POLL = 50
271
+ const KNOCK_DELAYS = [0, 500, 1000, 1500]
272
+ const PING_COOLDOWN = 5_000
@@ -1,4 +1,7 @@
1
+ import crypto from 'node:crypto'
2
+ import { buffer } from 'node:stream/consumers'
1
3
  import Negotiator from 'negotiator'
4
+ import { console } from 'openspan'
2
5
  import { Timing } from './Timing'
3
6
  import { type Format, formats, types } from './formats'
4
7
  import { read } from './messages'
@@ -6,6 +9,7 @@ import type { OutgoingMessage } from './messages'
6
9
  import type * as http from 'node:http'
7
10
 
8
11
  export class Context {
12
+ public readonly id: string
9
13
  public readonly authority: string
10
14
  public readonly request: IncomingMessage
11
15
  public readonly url: URL
@@ -19,19 +23,25 @@ export class Context {
19
23
  response: []
20
24
  }
21
25
 
22
- public constructor (authority: string, request: IncomingMessage, properties: Properties) {
26
+ private consumed = false
27
+
28
+ // eslint-disable-next-line max-params
29
+ public constructor (authority: string, request: IncomingMessage, properties: Properties,
30
+ url: URL) {
23
31
  this.authority = authority
24
32
  this.request = request
25
33
 
26
- this.url = new URL(request.url, `https://${request.headers.host}`)
27
- this.timing = new Timing(properties.trace)
34
+ this.id = crypto.randomUUID()
35
+ // parsed by the server, which had to parse it anyway to know the request is valid
36
+ this.url = url
37
+ this.timing = new Timing()
28
38
  this.debug = properties.debug
39
+ this.log(request)
29
40
 
30
- if (this.debug)
31
- this.log(request)
41
+ const accept = this.request.headers.accept
32
42
 
33
- if (this.request.headers.accept !== undefined) {
34
- const match = SUBTYPE.exec(this.request.headers.accept)
43
+ if (accept !== undefined) {
44
+ const match = SUBTYPE.exec(accept)
35
45
 
36
46
  if (match !== null) {
37
47
  const {
@@ -45,29 +55,35 @@ export class Context {
45
55
  }
46
56
  }
47
57
 
48
- const negotiator = new Negotiator(this.request)
49
- const mediaType = negotiator.mediaType(types)
58
+ const encoder = negotiate(this.request)
50
59
 
51
- if (mediaType !== undefined)
52
- this.encoder = formats[mediaType]
60
+ if (encoder !== undefined)
61
+ this.encoder = encoder
53
62
  }
54
63
 
55
- public async body<T> (): Promise<T> {
56
- const value = await read(this)
64
+ public async buffer (): Promise<Buffer> {
65
+ this.consumed = true
57
66
 
58
- return this.pipelines.body.length === 0
59
- ? value
60
- : this.pipelines.body.reduce((value, transform) => transform(value), value)
67
+ return await buffer(this.request)
68
+ }
69
+
70
+ public async body<T>(): Promise<T> {
71
+ let value = this.consumed ? null : await read(this)
72
+
73
+ for (const transform of this.pipelines.body)
74
+ value = await transform(value)
75
+
76
+ return value
61
77
  }
62
78
 
63
79
  private log (request: IncomingMessage): void {
64
- const message = `${request.method} ${request.url}`
65
- const { authorization, ...headers } = request.headers
80
+ const headers = { ...request.headers }
66
81
 
67
- if (authorization !== undefined)
68
- headers.authorization = authorization.slice(0, authorization.indexOf(' '))
82
+ if (headers.authorization !== undefined)
83
+ // only scheme
84
+ headers.authorization = headers.authorization.slice(0, headers.authorization.indexOf(' '))
69
85
 
70
- console.debug(message, headers)
86
+ console.debug('Received request', { method: request.method, url: request.url, headers })
71
87
  }
72
88
  }
73
89
 
@@ -78,12 +94,38 @@ export interface IncomingMessage extends http.IncomingMessage {
78
94
 
79
95
  interface Pipelines {
80
96
  body: Array<(input: unknown) => unknown>
81
- response: Array<(output: OutgoingMessage) => void>
97
+ response: Array<(output: OutgoingMessage) => void | Promise<void>>
82
98
  }
83
99
 
84
100
  interface Properties {
85
101
  debug: boolean
86
- trace: boolean
87
102
  }
88
103
 
104
+ /**
105
+ * Negotiation parses the header and sorts the candidates, and the value repeats:
106
+ * clients send one of a handful of `accept` strings. Bounded, the header is theirs.
107
+ */
108
+ function negotiate (request: IncomingMessage): Format | undefined {
109
+ const accept = request.headers.accept ?? ''
110
+ const known = NEGOTIATED.get(accept)
111
+
112
+ if (known !== undefined)
113
+ return known === NONE ? undefined : known
114
+
115
+ const mediaType = new Negotiator(request).mediaType(types)
116
+ const encoder = mediaType === undefined ? undefined : formats[mediaType]
117
+
118
+ if (NEGOTIATED.size >= NEGOTIATED_LIMIT)
119
+ NEGOTIATED.clear()
120
+
121
+ NEGOTIATED.set(accept, encoder ?? NONE)
122
+
123
+ return encoder
124
+ }
125
+
126
+ /** distinguishes "negotiated to nothing" from "not negotiated yet" */
127
+ const NONE = Symbol('not acceptable') as unknown as Format
128
+ const NEGOTIATED = new Map<string, Format>()
129
+ const NEGOTIATED_LIMIT = 1024
130
+
89
131
  const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/