@toa.io/extensions.exposition 1.0.0-alpha.0 → 1.0.0-alpha.2

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 (442) hide show
  1. package/components/context.toa.yaml +12 -0
  2. package/components/identity.bans/manifest.toa.yaml +1 -1
  3. package/components/identity.basic/manifest.toa.yaml +2 -2
  4. package/components/identity.basic/operations/authenticate.d.ts +9 -0
  5. package/components/identity.basic/operations/authenticate.js +24 -0
  6. package/components/identity.basic/operations/authenticate.js.map +1 -0
  7. package/components/identity.basic/operations/create.d.ts +10 -0
  8. package/components/identity.basic/operations/create.js +10 -0
  9. package/components/identity.basic/operations/create.js.map +1 -0
  10. package/components/identity.basic/operations/transit.d.ts +12 -0
  11. package/components/identity.basic/operations/transit.js +53 -0
  12. package/components/identity.basic/operations/transit.js.map +1 -0
  13. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -0
  14. package/components/identity.basic/operations/types.d.ts +38 -0
  15. package/components/identity.basic/operations/types.js +3 -0
  16. package/components/identity.basic/operations/types.js.map +1 -0
  17. package/components/identity.basic/source/authenticate.ts +0 -1
  18. package/components/identity.federation/events/principal.js +22 -0
  19. package/components/identity.federation/manifest.toa.yaml +88 -0
  20. package/components/identity.federation/operations/assertions-as-values.cjs +45 -0
  21. package/components/identity.federation/operations/assertions-as-values.cjs.map +1 -0
  22. package/components/identity.federation/operations/assertions-as-values.d.cts +4 -0
  23. package/components/identity.federation/operations/authenticate.d.ts +3 -0
  24. package/components/identity.federation/operations/authenticate.js +20 -0
  25. package/components/identity.federation/operations/authenticate.js.map +1 -0
  26. package/components/identity.federation/operations/create.d.ts +10 -0
  27. package/components/identity.federation/operations/create.js +15 -0
  28. package/components/identity.federation/operations/create.js.map +1 -0
  29. package/components/identity.federation/operations/jwt.cjs +112 -0
  30. package/components/identity.federation/operations/jwt.cjs.map +1 -0
  31. package/components/identity.federation/operations/jwt.d.cts +19 -0
  32. package/components/identity.federation/operations/schemas.d.ts +43 -0
  33. package/components/identity.federation/operations/schemas.js +9 -0
  34. package/components/identity.federation/operations/schemas.js.map +1 -0
  35. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -0
  36. package/components/identity.federation/operations/types.d.ts +51 -0
  37. package/components/identity.federation/operations/types.js +3 -0
  38. package/components/identity.federation/operations/types.js.map +1 -0
  39. package/components/identity.federation/source/assertions-as-values.cts +20 -0
  40. package/components/identity.federation/source/authenticate.ts +28 -0
  41. package/components/identity.federation/source/create.ts +26 -0
  42. package/components/identity.federation/source/jwt.cts +143 -0
  43. package/components/identity.federation/source/schemas.ts +45 -0
  44. package/components/identity.federation/source/types.ts +56 -0
  45. package/components/identity.federation/tsconfig.json +9 -0
  46. package/components/identity.roles/operations/list.d.ts +5 -0
  47. package/components/identity.roles/operations/list.js +8 -0
  48. package/components/identity.roles/operations/list.js.map +1 -0
  49. package/components/identity.roles/operations/principal.d.ts +15 -0
  50. package/components/identity.roles/operations/principal.js +8 -0
  51. package/components/identity.roles/operations/principal.js.map +1 -0
  52. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -0
  53. package/components/identity.tokens/manifest.toa.yaml +1 -1
  54. package/components/identity.tokens/operations/authenticate.d.ts +9 -0
  55. package/components/identity.tokens/operations/authenticate.js +32 -0
  56. package/components/identity.tokens/operations/authenticate.js.map +1 -0
  57. package/components/identity.tokens/operations/decrypt.d.ts +3 -0
  58. package/components/identity.tokens/operations/decrypt.js +32 -0
  59. package/components/identity.tokens/operations/decrypt.js.map +1 -0
  60. package/components/identity.tokens/operations/encrypt.d.ts +8 -0
  61. package/components/identity.tokens/operations/encrypt.js +22 -0
  62. package/components/identity.tokens/operations/encrypt.js.map +1 -0
  63. package/components/identity.tokens/operations/revoke.d.ts +2 -0
  64. package/components/identity.tokens/operations/revoke.js +8 -0
  65. package/components/identity.tokens/operations/revoke.js.map +1 -0
  66. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -0
  67. package/components/identity.tokens/operations/types.d.ts +40 -0
  68. package/components/identity.tokens/operations/types.js +3 -0
  69. package/components/identity.tokens/operations/types.js.map +1 -0
  70. package/components/octets.storage/manifest.toa.yaml +1 -0
  71. package/components/octets.storage/operations/store.js +2 -2
  72. package/cucumber.js +0 -1
  73. package/documentation/components.md +25 -2
  74. package/documentation/identity.md +7 -7
  75. package/documentation/octets.md +93 -40
  76. package/documentation/protocol.md +21 -1
  77. package/documentation/query.md +1 -1
  78. package/documentation/vary.md +69 -0
  79. package/features/cors.feature +72 -0
  80. package/features/identity.feature +19 -3
  81. package/features/identity.federation.feature +125 -0
  82. package/features/octets.entries.feature +121 -0
  83. package/features/octets.feature +2 -28
  84. package/features/octets.meta.feature +65 -0
  85. package/features/octets.workflows.feature +138 -4
  86. package/features/response.feature +65 -0
  87. package/features/routes.feature +37 -0
  88. package/features/steps/Captures.ts +6 -0
  89. package/features/steps/Components.ts +18 -6
  90. package/features/steps/Gateway.ts +1 -2
  91. package/features/steps/HTTP.ts +40 -87
  92. package/features/steps/IdP.ts +120 -0
  93. package/features/steps/Parameters.ts +8 -2
  94. package/features/steps/Workspace.ts +5 -7
  95. package/features/steps/components/echo/operations/error.js +11 -0
  96. package/features/steps/components/octets.tester/manifest.toa.yaml +3 -0
  97. package/features/steps/components/octets.tester/operations/concat.js +7 -0
  98. package/features/steps/components/octets.tester/operations/echo.js +7 -0
  99. package/features/steps/components/users/manifest.toa.yaml +3 -0
  100. package/features/steps/components/users.properties/manifest.toa.yaml +13 -0
  101. package/features/steps/tsconfig.json +1 -1
  102. package/features/vary.feature +150 -0
  103. package/package.json +17 -18
  104. package/schemas/octets/delete.cos.yaml +2 -1
  105. package/schemas/octets/list.cos.yaml +2 -1
  106. package/source/Directive.test.ts +8 -2
  107. package/source/Directive.ts +19 -16
  108. package/source/Factory.ts +8 -7
  109. package/source/Gateway.ts +22 -8
  110. package/source/HTTP/Server.fixtures.ts +0 -1
  111. package/source/HTTP/Server.test.ts +61 -134
  112. package/source/HTTP/Server.ts +91 -47
  113. package/source/HTTP/formats/msgpack.ts +9 -6
  114. package/source/HTTP/formats/text.ts +1 -1
  115. package/source/HTTP/formats/yaml.ts +1 -1
  116. package/source/HTTP/messages.ts +15 -3
  117. package/source/Interception.ts +24 -0
  118. package/source/RTD/Directives.ts +2 -2
  119. package/source/RTD/Tree.ts +3 -0
  120. package/source/RTD/syntax/parse.ts +6 -6
  121. package/source/RTD/syntax/types.ts +1 -1
  122. package/source/deployment.ts +1 -2
  123. package/source/directives/auth/{Family.ts → Authorization.ts} +29 -33
  124. package/source/directives/auth/Incept.ts +1 -1
  125. package/source/directives/auth/Rule.ts +2 -2
  126. package/source/directives/auth/index.ts +2 -2
  127. package/source/directives/auth/schemes.ts +2 -1
  128. package/source/directives/auth/types.ts +9 -6
  129. package/source/directives/cache/{Family.ts → Cache.ts} +4 -5
  130. package/source/directives/cache/index.ts +2 -2
  131. package/source/directives/cache/types.ts +1 -1
  132. package/source/directives/cors/CORS.ts +54 -0
  133. package/source/directives/cors/index.ts +3 -0
  134. package/source/directives/dev/{Family.ts → Development.ts} +3 -4
  135. package/source/directives/dev/Stub.ts +4 -4
  136. package/source/directives/dev/Throw.ts +4 -4
  137. package/source/directives/dev/index.ts +2 -2
  138. package/source/directives/dev/types.ts +1 -1
  139. package/source/directives/index.ts +10 -6
  140. package/source/directives/octets/Context.ts +1 -1
  141. package/source/directives/octets/Delete.ts +50 -9
  142. package/source/directives/octets/Fetch.ts +18 -19
  143. package/source/directives/octets/List.ts +37 -7
  144. package/source/directives/octets/{Family.ts → Octets.ts} +7 -6
  145. package/source/directives/octets/Permute.ts +3 -3
  146. package/source/directives/octets/Store.ts +43 -99
  147. package/source/directives/octets/index.ts +2 -2
  148. package/source/directives/octets/schemas.ts +11 -6
  149. package/source/directives/octets/types.ts +4 -3
  150. package/source/directives/octets/workflow/Execution.ts +78 -0
  151. package/source/directives/octets/workflow/Workflow.ts +37 -0
  152. package/source/directives/octets/workflow/index.ts +1 -0
  153. package/source/directives/vary/Directive.ts +6 -0
  154. package/source/directives/vary/Embed.ts +62 -0
  155. package/source/directives/vary/Properties.ts +17 -0
  156. package/source/directives/vary/Vary.ts +48 -0
  157. package/source/directives/vary/embeddings/Embedding.ts +6 -0
  158. package/source/directives/vary/embeddings/Header.ts +30 -0
  159. package/source/directives/vary/embeddings/Language.ts +31 -0
  160. package/source/directives/vary/embeddings/index.ts +11 -0
  161. package/source/directives/vary/index.ts +3 -0
  162. package/source/io.ts +4 -0
  163. package/source/manifest.test.ts +6 -14
  164. package/source/manifest.ts +9 -6
  165. package/source/schemas.ts +7 -3
  166. package/transpiled/Annotation.d.ts +7 -0
  167. package/transpiled/Annotation.js +3 -0
  168. package/transpiled/Annotation.js.map +1 -0
  169. package/transpiled/Branch.d.ts +7 -0
  170. package/transpiled/Branch.js +3 -0
  171. package/transpiled/Branch.js.map +1 -0
  172. package/transpiled/Composition.d.ts +14 -0
  173. package/transpiled/Composition.js +43 -0
  174. package/transpiled/Composition.js.map +1 -0
  175. package/transpiled/Context.d.ts +5 -0
  176. package/transpiled/Context.js +3 -0
  177. package/transpiled/Context.js.map +1 -0
  178. package/transpiled/Directive.d.ts +31 -0
  179. package/transpiled/Directive.js +78 -0
  180. package/transpiled/Directive.js.map +1 -0
  181. package/transpiled/Endpoint.d.ts +20 -0
  182. package/transpiled/Endpoint.js +45 -0
  183. package/transpiled/Endpoint.js.map +1 -0
  184. package/transpiled/Factory.d.ts +9 -0
  185. package/transpiled/Factory.js +67 -0
  186. package/transpiled/Factory.js.map +1 -0
  187. package/transpiled/Gateway.d.ts +22 -0
  188. package/transpiled/Gateway.js +102 -0
  189. package/transpiled/Gateway.js.map +1 -0
  190. package/transpiled/HTTP/Server.d.ts +24 -0
  191. package/transpiled/HTTP/Server.fixtures.d.ts +10 -0
  192. package/transpiled/HTTP/Server.fixtures.js +31 -0
  193. package/transpiled/HTTP/Server.fixtures.js.map +1 -0
  194. package/transpiled/HTTP/Server.js +149 -0
  195. package/transpiled/HTTP/Server.js.map +1 -0
  196. package/transpiled/HTTP/exceptions.d.ts +34 -0
  197. package/transpiled/HTTP/exceptions.js +71 -0
  198. package/transpiled/HTTP/exceptions.js.map +1 -0
  199. package/transpiled/HTTP/formats/index.d.ts +10 -0
  200. package/transpiled/HTTP/formats/index.js +38 -0
  201. package/transpiled/HTTP/formats/index.js.map +1 -0
  202. package/transpiled/HTTP/formats/json.d.ts +6 -0
  203. package/transpiled/HTTP/formats/json.js +17 -0
  204. package/transpiled/HTTP/formats/json.js.map +1 -0
  205. package/transpiled/HTTP/formats/msgpack.d.ts +6 -0
  206. package/transpiled/HTTP/formats/msgpack.js +17 -0
  207. package/transpiled/HTTP/formats/msgpack.js.map +1 -0
  208. package/transpiled/HTTP/formats/text.d.ts +8 -0
  209. package/transpiled/HTTP/formats/text.js +15 -0
  210. package/transpiled/HTTP/formats/text.js.map +1 -0
  211. package/transpiled/HTTP/formats/yaml.d.ts +6 -0
  212. package/transpiled/HTTP/formats/yaml.js +41 -0
  213. package/transpiled/HTTP/formats/yaml.js.map +1 -0
  214. package/transpiled/HTTP/index.d.ts +3 -0
  215. package/transpiled/HTTP/index.js +20 -0
  216. package/transpiled/HTTP/index.js.map +1 -0
  217. package/transpiled/HTTP/messages.d.ts +33 -0
  218. package/transpiled/HTTP/messages.js +75 -0
  219. package/transpiled/HTTP/messages.js.map +1 -0
  220. package/transpiled/Interception.d.ts +9 -0
  221. package/transpiled/Interception.js +19 -0
  222. package/transpiled/Interception.js.map +1 -0
  223. package/transpiled/Mapping.d.ts +8 -0
  224. package/transpiled/Mapping.js +38 -0
  225. package/transpiled/Mapping.js.map +1 -0
  226. package/transpiled/Query.d.ts +13 -0
  227. package/transpiled/Query.js +107 -0
  228. package/transpiled/Query.js.map +1 -0
  229. package/transpiled/RTD/Context.d.ts +11 -0
  230. package/transpiled/RTD/Context.js +3 -0
  231. package/transpiled/RTD/Context.js.map +1 -0
  232. package/transpiled/RTD/Directives.d.ts +7 -0
  233. package/transpiled/RTD/Directives.js +3 -0
  234. package/transpiled/RTD/Directives.js.map +1 -0
  235. package/transpiled/RTD/Endpoint.d.ts +9 -0
  236. package/transpiled/RTD/Endpoint.js +3 -0
  237. package/transpiled/RTD/Endpoint.js.map +1 -0
  238. package/transpiled/RTD/Match.d.ts +11 -0
  239. package/transpiled/RTD/Match.js +3 -0
  240. package/transpiled/RTD/Match.js.map +1 -0
  241. package/transpiled/RTD/Method.d.ts +9 -0
  242. package/transpiled/RTD/Method.js +16 -0
  243. package/transpiled/RTD/Method.js.map +1 -0
  244. package/transpiled/RTD/Node.d.ts +21 -0
  245. package/transpiled/RTD/Node.js +61 -0
  246. package/transpiled/RTD/Node.js.map +1 -0
  247. package/transpiled/RTD/Route.d.ts +14 -0
  248. package/transpiled/RTD/Route.js +49 -0
  249. package/transpiled/RTD/Route.js.map +1 -0
  250. package/transpiled/RTD/Tree.d.ts +14 -0
  251. package/transpiled/RTD/Tree.js +42 -0
  252. package/transpiled/RTD/Tree.js.map +1 -0
  253. package/transpiled/RTD/factory.d.ts +6 -0
  254. package/transpiled/RTD/factory.js +36 -0
  255. package/transpiled/RTD/factory.js.map +1 -0
  256. package/transpiled/RTD/index.d.ts +8 -0
  257. package/transpiled/RTD/index.js +38 -0
  258. package/transpiled/RTD/index.js.map +1 -0
  259. package/transpiled/RTD/segment.d.ts +8 -0
  260. package/transpiled/RTD/segment.js +25 -0
  261. package/transpiled/RTD/segment.js.map +1 -0
  262. package/transpiled/RTD/syntax/index.d.ts +2 -0
  263. package/transpiled/RTD/syntax/index.js +19 -0
  264. package/transpiled/RTD/syntax/index.js.map +1 -0
  265. package/transpiled/RTD/syntax/parse.d.ts +4 -0
  266. package/transpiled/RTD/syntax/parse.js +128 -0
  267. package/transpiled/RTD/syntax/parse.js.map +1 -0
  268. package/transpiled/RTD/syntax/types.d.ts +41 -0
  269. package/transpiled/RTD/syntax/types.js +5 -0
  270. package/transpiled/RTD/syntax/types.js.map +1 -0
  271. package/transpiled/Remotes.d.ts +9 -0
  272. package/transpiled/Remotes.js +25 -0
  273. package/transpiled/Remotes.js.map +1 -0
  274. package/transpiled/Tenant.d.ts +13 -0
  275. package/transpiled/Tenant.js +34 -0
  276. package/transpiled/Tenant.js.map +1 -0
  277. package/transpiled/deployment.d.ts +3 -0
  278. package/transpiled/deployment.js +66 -0
  279. package/transpiled/deployment.js.map +1 -0
  280. package/transpiled/directives/auth/Anonymous.d.ts +6 -0
  281. package/transpiled/directives/auth/Anonymous.js +17 -0
  282. package/transpiled/directives/auth/Anonymous.js.map +1 -0
  283. package/transpiled/directives/auth/Authorization.d.ts +20 -0
  284. package/transpiled/directives/auth/Authorization.js +125 -0
  285. package/transpiled/directives/auth/Authorization.js.map +1 -0
  286. package/transpiled/directives/auth/Echo.d.ts +6 -0
  287. package/transpiled/directives/auth/Echo.js +13 -0
  288. package/transpiled/directives/auth/Echo.js.map +1 -0
  289. package/transpiled/directives/auth/Id.d.ts +7 -0
  290. package/transpiled/directives/auth/Id.js +17 -0
  291. package/transpiled/directives/auth/Id.js.map +1 -0
  292. package/transpiled/directives/auth/Incept.d.ts +10 -0
  293. package/transpiled/directives/auth/Incept.js +58 -0
  294. package/transpiled/directives/auth/Incept.js.map +1 -0
  295. package/transpiled/directives/auth/Role.d.ts +11 -0
  296. package/transpiled/directives/auth/Role.js +44 -0
  297. package/transpiled/directives/auth/Role.js.map +1 -0
  298. package/transpiled/directives/auth/Rule.d.ts +9 -0
  299. package/transpiled/directives/auth/Rule.js +22 -0
  300. package/transpiled/directives/auth/Rule.js.map +1 -0
  301. package/transpiled/directives/auth/Scheme.d.ts +7 -0
  302. package/transpiled/directives/auth/Scheme.js +47 -0
  303. package/transpiled/directives/auth/Scheme.js.map +1 -0
  304. package/transpiled/directives/auth/index.d.ts +2 -0
  305. package/transpiled/directives/auth/index.js +6 -0
  306. package/transpiled/directives/auth/index.js.map +1 -0
  307. package/transpiled/directives/auth/schemes.d.ts +3 -0
  308. package/transpiled/directives/auth/schemes.js +10 -0
  309. package/transpiled/directives/auth/schemes.js.map +1 -0
  310. package/transpiled/directives/auth/split.d.ts +2 -0
  311. package/transpiled/directives/auth/split.js +38 -0
  312. package/transpiled/directives/auth/split.js.map +1 -0
  313. package/transpiled/directives/auth/types.d.ts +31 -0
  314. package/transpiled/directives/auth/types.js +3 -0
  315. package/transpiled/directives/auth/types.js.map +1 -0
  316. package/transpiled/directives/cache/Cache.d.ts +11 -0
  317. package/transpiled/directives/cache/Cache.js +28 -0
  318. package/transpiled/directives/cache/Cache.js.map +1 -0
  319. package/transpiled/directives/cache/Control.d.ts +9 -0
  320. package/transpiled/directives/cache/Control.js +42 -0
  321. package/transpiled/directives/cache/Control.js.map +1 -0
  322. package/transpiled/directives/cache/Exact.d.ts +4 -0
  323. package/transpiled/directives/cache/Exact.js +11 -0
  324. package/transpiled/directives/cache/Exact.js.map +1 -0
  325. package/transpiled/directives/cache/index.d.ts +2 -0
  326. package/transpiled/directives/cache/index.js +6 -0
  327. package/transpiled/directives/cache/index.js.map +1 -0
  328. package/transpiled/directives/cache/types.d.ts +7 -0
  329. package/transpiled/directives/cache/types.js +3 -0
  330. package/transpiled/directives/cache/types.js.map +1 -0
  331. package/transpiled/directives/cors/CORS.d.ts +11 -0
  332. package/transpiled/directives/cors/CORS.js +44 -0
  333. package/transpiled/directives/cors/CORS.js.map +1 -0
  334. package/transpiled/directives/cors/index.d.ts +2 -0
  335. package/transpiled/directives/cors/index.js +6 -0
  336. package/transpiled/directives/cors/index.js.map +1 -0
  337. package/transpiled/directives/dev/Development.d.ts +9 -0
  338. package/transpiled/directives/dev/Development.js +29 -0
  339. package/transpiled/directives/dev/Development.js.map +1 -0
  340. package/transpiled/directives/dev/Stub.d.ts +7 -0
  341. package/transpiled/directives/dev/Stub.js +14 -0
  342. package/transpiled/directives/dev/Stub.js.map +1 -0
  343. package/transpiled/directives/dev/Throw.d.ts +7 -0
  344. package/transpiled/directives/dev/Throw.js +14 -0
  345. package/transpiled/directives/dev/Throw.js.map +1 -0
  346. package/transpiled/directives/dev/index.d.ts +2 -0
  347. package/transpiled/directives/dev/index.js +6 -0
  348. package/transpiled/directives/dev/index.js.map +1 -0
  349. package/transpiled/directives/dev/types.d.ts +4 -0
  350. package/transpiled/directives/dev/types.js +3 -0
  351. package/transpiled/directives/dev/types.js.map +1 -0
  352. package/transpiled/directives/index.d.ts +4 -0
  353. package/transpiled/directives/index.js +12 -0
  354. package/transpiled/directives/index.js.map +1 -0
  355. package/transpiled/directives/octets/Context.d.ts +8 -0
  356. package/transpiled/directives/octets/Context.js +40 -0
  357. package/transpiled/directives/octets/Context.js.map +1 -0
  358. package/transpiled/directives/octets/Delete.d.ts +19 -0
  359. package/transpiled/directives/octets/Delete.js +72 -0
  360. package/transpiled/directives/octets/Delete.js.map +1 -0
  361. package/transpiled/directives/octets/Fetch.d.ts +17 -0
  362. package/transpiled/directives/octets/Fetch.js +76 -0
  363. package/transpiled/directives/octets/Fetch.js.map +1 -0
  364. package/transpiled/directives/octets/List.d.ts +15 -0
  365. package/transpiled/directives/octets/List.js +65 -0
  366. package/transpiled/directives/octets/List.js.map +1 -0
  367. package/transpiled/directives/octets/Octets.d.ts +12 -0
  368. package/transpiled/directives/octets/Octets.js +51 -0
  369. package/transpiled/directives/octets/Octets.js.map +1 -0
  370. package/transpiled/directives/octets/Permute.d.ts +10 -0
  371. package/transpiled/directives/octets/Permute.js +51 -0
  372. package/transpiled/directives/octets/Permute.js.map +1 -0
  373. package/transpiled/directives/octets/Store.d.ts +22 -0
  374. package/transpiled/directives/octets/Store.js +80 -0
  375. package/transpiled/directives/octets/Store.js.map +1 -0
  376. package/transpiled/directives/octets/index.d.ts +2 -0
  377. package/transpiled/directives/octets/index.js +6 -0
  378. package/transpiled/directives/octets/index.js.map +1 -0
  379. package/transpiled/directives/octets/schemas.d.ts +11 -0
  380. package/transpiled/directives/octets/schemas.js +17 -0
  381. package/transpiled/directives/octets/schemas.js.map +1 -0
  382. package/transpiled/directives/octets/types.d.ts +10 -0
  383. package/transpiled/directives/octets/types.js +3 -0
  384. package/transpiled/directives/octets/types.js.map +1 -0
  385. package/transpiled/directives/octets/workflow/Execution.d.ts +25 -0
  386. package/transpiled/directives/octets/workflow/Execution.js +55 -0
  387. package/transpiled/directives/octets/workflow/Execution.js.map +1 -0
  388. package/transpiled/directives/octets/workflow/Workflow.d.ts +12 -0
  389. package/transpiled/directives/octets/workflow/Workflow.js +25 -0
  390. package/transpiled/directives/octets/workflow/Workflow.js.map +1 -0
  391. package/transpiled/directives/octets/workflow/index.d.ts +1 -0
  392. package/transpiled/directives/octets/workflow/index.js +6 -0
  393. package/transpiled/directives/octets/workflow/index.js.map +1 -0
  394. package/transpiled/directives/vary/Directive.d.ts +5 -0
  395. package/transpiled/directives/vary/Directive.js +3 -0
  396. package/transpiled/directives/vary/Directive.js.map +1 -0
  397. package/transpiled/directives/vary/Embed.d.ts +10 -0
  398. package/transpiled/directives/vary/Embed.js +49 -0
  399. package/transpiled/directives/vary/Embed.js.map +1 -0
  400. package/transpiled/directives/vary/Properties.d.ts +9 -0
  401. package/transpiled/directives/vary/Properties.js +16 -0
  402. package/transpiled/directives/vary/Properties.js.map +1 -0
  403. package/transpiled/directives/vary/Vary.d.ts +10 -0
  404. package/transpiled/directives/vary/Vary.js +36 -0
  405. package/transpiled/directives/vary/Vary.js.map +1 -0
  406. package/transpiled/directives/vary/embeddings/Embedding.d.ts +5 -0
  407. package/transpiled/directives/vary/embeddings/Embedding.js +3 -0
  408. package/transpiled/directives/vary/embeddings/Embedding.js.map +1 -0
  409. package/transpiled/directives/vary/embeddings/Header.d.ts +7 -0
  410. package/transpiled/directives/vary/embeddings/Header.js +26 -0
  411. package/transpiled/directives/vary/embeddings/Header.js.map +1 -0
  412. package/transpiled/directives/vary/embeddings/Language.d.ts +7 -0
  413. package/transpiled/directives/vary/embeddings/Language.js +28 -0
  414. package/transpiled/directives/vary/embeddings/Language.js.map +1 -0
  415. package/transpiled/directives/vary/embeddings/index.d.ts +5 -0
  416. package/transpiled/directives/vary/embeddings/index.js +10 -0
  417. package/transpiled/directives/vary/embeddings/index.js.map +1 -0
  418. package/transpiled/directives/vary/index.d.ts +2 -0
  419. package/transpiled/directives/vary/index.js +6 -0
  420. package/transpiled/directives/vary/index.js.map +1 -0
  421. package/transpiled/discovery.d.ts +1 -0
  422. package/transpiled/discovery.js +3 -0
  423. package/transpiled/discovery.js.map +1 -0
  424. package/transpiled/exceptions.d.ts +2 -0
  425. package/transpiled/exceptions.js +39 -0
  426. package/transpiled/exceptions.js.map +1 -0
  427. package/transpiled/index.d.ts +5 -0
  428. package/transpiled/index.js +12 -0
  429. package/transpiled/index.js.map +1 -0
  430. package/transpiled/io.d.ts +3 -0
  431. package/transpiled/io.js +3 -0
  432. package/transpiled/io.js.map +1 -0
  433. package/transpiled/manifest.d.ts +3 -0
  434. package/transpiled/manifest.js +66 -0
  435. package/transpiled/manifest.js.map +1 -0
  436. package/transpiled/root.d.ts +2 -0
  437. package/transpiled/root.js +39 -0
  438. package/transpiled/root.js.map +1 -0
  439. package/transpiled/schemas.d.ts +7 -0
  440. package/transpiled/schemas.js +14 -0
  441. package/transpiled/schemas.js.map +1 -0
  442. package/transpiled/tsconfig.tsbuildinfo +1 -0
@@ -1,17 +1,21 @@
1
- import { type IncomingMessage, type OutgoingMessage } from './HTTP'
2
- import { type Remotes } from './Remotes'
1
+ import type { IncomingMessage, 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
6
  export class Directives implements RTD.Directives<Directives> {
6
- private readonly directives: DirectiveSet[]
7
+ private readonly sets: DirectiveSet[]
7
8
 
8
- public constructor (directives: DirectiveSet[]) {
9
- this.directives = directives
9
+ public constructor (sets: DirectiveSet[]) {
10
+ this.sets = sets
10
11
  }
11
12
 
12
13
  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)
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, request, parameters)
15
19
 
16
20
  if (output !== null) {
17
21
  await this.settle(request, output)
@@ -24,13 +28,13 @@ export class Directives implements RTD.Directives<Directives> {
24
28
  }
25
29
 
26
30
  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)
31
+ for (const set of this.sets)
32
+ if (set.family.settle !== undefined)
33
+ await set.family.settle(set.directives, request, response)
30
34
  }
31
35
 
32
36
  public merge (directives: Directives): void {
33
- this.directives.push(...directives.directives)
37
+ this.sets.push(...directives.sets)
34
38
  }
35
39
  }
36
40
 
@@ -61,7 +65,7 @@ export class DirectivesFactory implements RTD.DirectivesFactory<Directives> {
61
65
  const family = this.families[declaration.family]
62
66
 
63
67
  if (family === undefined)
64
- throw new Error(`Directive family '${declaration.family}' not found.`)
68
+ throw new Error(`Directive family '${declaration.family}' is not found.`)
65
69
 
66
70
  const directive = family.create(declaration.name, declaration.value, this.remtoes)
67
71
 
@@ -100,9 +104,11 @@ export interface Family<TDirective = any, TExtension = any> {
100
104
  readonly name: string
101
105
  readonly mandatory: boolean
102
106
 
107
+ // produce: (declarations: RTD.syntax.Directive[], remotes: Remotes) => TDirective[]
108
+
103
109
  create: (name: string, value: any, remotes: Remotes) => TDirective
104
110
 
105
- preflight: (directives: TDirective[],
111
+ preflight?: (directives: TDirective[],
106
112
  request: IncomingMessage & TExtension,
107
113
  parameters: RTD.Parameter[]) => Output | Promise<Output>
108
114
 
@@ -115,6 +121,3 @@ interface DirectiveSet {
115
121
  family: Family
116
122
  directives: any[]
117
123
  }
118
-
119
- export type Input = IncomingMessage
120
- export type Output = OutgoingMessage | null
package/source/Factory.ts CHANGED
@@ -4,19 +4,18 @@ import { Remotes } from './Remotes'
4
4
  import { Tree, syntax } from './RTD'
5
5
  import { Server } from './HTTP'
6
6
  import { type Endpoint, EndpointsFactory } from './Endpoint'
7
- import * as directives from './directives'
8
- import { type Directives, DirectivesFactory, type Family } from './Directive'
7
+ import { families, interceptors } from './directives'
8
+ import { type Directives, DirectivesFactory } from './Directive'
9
9
  import { Composition } from './Composition'
10
10
  import * as root from './root'
11
+ import { Interception } from './Interception'
11
12
  import type { Connector, Locator, extensions } from '@toa.io/core'
12
13
 
13
14
  export class Factory implements extensions.Factory {
14
15
  private readonly boot: Bootloader
15
- private readonly families: Family[]
16
16
 
17
17
  public constructor (boot: Bootloader) {
18
18
  this.boot = boot
19
- this.families = directives.families
20
19
  }
21
20
 
22
21
  public tenant (locator: Locator, node: syntax.Node): Connector {
@@ -32,16 +31,18 @@ export class Factory implements extensions.Factory {
32
31
  const remotes = new Remotes(this.boot)
33
32
  const node = root.resolve()
34
33
  const methods = new EndpointsFactory(remotes)
35
- const directives = new DirectivesFactory(this.families, remotes)
34
+ const directives = new DirectivesFactory(families, remotes)
35
+ const interception = new Interception(interceptors)
36
36
  const tree = new Tree<Endpoint, Directives>(node, methods, directives)
37
37
 
38
38
  const composition = new Composition(this.boot)
39
- const gateway = new Gateway(broadcast, server, tree)
39
+ const gateway = new Gateway(broadcast, server, tree, interception)
40
40
 
41
41
  gateway.depends(remotes)
42
42
  gateway.depends(composition)
43
+ server.depends(gateway)
43
44
 
44
- return gateway
45
+ return server
45
46
  }
46
47
  }
47
48
 
package/source/Gateway.ts CHANGED
@@ -1,25 +1,31 @@
1
1
  import { type bindings, Connector } from '@toa.io/core'
2
- import { type Maybe } from '@toa.io/types'
3
2
  import * as http from './HTTP'
4
3
  import { rethrow } from './exceptions'
5
- import { type Method, type Parameter, type Tree } from './RTD'
6
- import { type Label } from './discovery'
7
- import { type Branch } from './Branch'
8
- import { type Endpoint } from './Endpoint'
9
- import { type Directives } from './Directive'
4
+ import type { Interceptor } from './Interception'
5
+ import type { Maybe } from '@toa.io/types'
6
+ import type { Method, Parameter, Tree } from './RTD'
7
+ import type { Label } from './discovery'
8
+ import type { Branch } from './Branch'
9
+ import type { Endpoint } from './Endpoint'
10
+ import type { Directives } from './Directive'
10
11
 
11
12
  export class Gateway extends Connector {
12
13
  private readonly broadcast: Broadcast
13
14
  private readonly tree: Tree<Endpoint, Directives>
15
+ private readonly interceptor: Interceptor
16
+ private readonly server: Connector
14
17
 
15
- public constructor (broadcast: Broadcast, server: http.Server, tree: Tree<Endpoint, Directives>) {
18
+ // eslint-disable-next-line max-params, max-len
19
+ public constructor (broadcast: Broadcast, server: http.Server, tree: Tree<Endpoint, Directives>, interception: Interceptor) {
16
20
  super()
17
21
 
18
22
  this.broadcast = broadcast
19
23
  this.tree = tree
24
+ this.interceptor = interception
25
+ this.server = server
20
26
 
21
27
  this.depends(broadcast)
22
- this.depends(server)
28
+ // this.depends(server)
23
29
 
24
30
  server.attach(this.process.bind(this))
25
31
  }
@@ -35,6 +41,11 @@ export class Gateway extends Connector {
35
41
  }
36
42
 
37
43
  private async process (request: http.IncomingMessage): Promise<http.OutgoingMessage> {
44
+ const interception = await this.interceptor.intercept(request)
45
+
46
+ if (interception !== null)
47
+ return interception
48
+
38
49
  const match = this.tree.match(request.path)
39
50
 
40
51
  if (match === null)
@@ -68,6 +79,9 @@ export class Gateway extends Connector {
68
79
 
69
80
  const body = await request.parse()
70
81
 
82
+ if ('embed' in request && typeof body === 'object' && body !== null)
83
+ Object.assign(body, request.embed)
84
+
71
85
  const reply = await method.endpoint
72
86
  .call(body, request.query, parameters)
73
87
  .catch(rethrow) as Maybe<unknown>
@@ -1,4 +1,3 @@
1
- import { Buffer } from 'buffer'
2
1
  import { Readable } from 'stream'
3
2
  import type { IncomingMessage } from './messages'
4
3
  import type * as http from 'node:http'
@@ -1,199 +1,126 @@
1
+ import { randomUUID } from 'node:crypto'
1
2
  import { Connector } from '@toa.io/core'
2
- import { immediate } from '@toa.io/generic'
3
- import { generate } from 'randomstring'
4
3
  import { type Processing, Server } from './Server'
5
4
  import { type OutgoingMessage } from './messages'
6
- import { express, cors, createRequest, res, next } from './Server.fixtures'
7
5
  import { BadRequest } from './exceptions'
8
- import type { Express, Request, RequestHandler } from 'express'
9
- import type { CorsOptions } from 'cors'
10
- import type http from 'node:http'
11
-
12
- jest.mock('express', () => () => express())
13
- jest.mock('cors', () => (options: CorsOptions) => cors(options))
14
6
 
15
7
  let server: Server
16
- let app: jest.MockedObject<Express>
17
-
18
- beforeEach(() => {
19
- jest.clearAllMocks()
20
8
 
21
- server = Server.create()
22
- app = express.mock.results[0]?.value
9
+ beforeAll(() => {
10
+ server = Server.create({ port: 0 })
23
11
  })
24
12
 
25
13
  it('should instance of connector', async () => {
26
14
  expect(server).toBeInstanceOf(Connector)
27
15
  })
28
16
 
29
- it('should create express app', async () => {
30
- expect(express).toHaveBeenCalled()
31
- expect(app.disable).toHaveBeenCalledWith('x-powered-by')
32
- })
33
-
34
- it('should support cors', async () => {
35
- expect(cors).toHaveBeenCalledWith({ allowedHeaders: ['content-type'] } satisfies CorsOptions)
36
-
37
- const middleware = cors.mock.results[0].value
38
-
39
- expect(app.use).toHaveBeenCalledWith(middleware)
40
- })
41
-
42
17
  it('should start HTTP server', async () => {
43
- const stared = server.connect()
44
-
45
- await immediate()
46
-
47
- expect(app.listen).toHaveBeenCalledWith(8000, expect.anything())
48
-
49
- const done = app.listen.mock.calls[0][1]
50
-
51
- if (done !== undefined) done()
18
+ await server.connect()
52
19
 
53
- await stared
54
- })
55
-
56
- it('should stop HTTP server', async () => {
57
- const started = server.connect()
58
-
59
- await immediate()
60
-
61
- app.listen.mock.calls[0][1]?.() // `listen` callback
62
-
63
- await started
64
-
65
- const stopped = server.disconnect()
66
- const httpServer: jest.MockedObject<http.Server> = app.listen.mock.results[0].value
67
-
68
- await immediate()
69
-
70
- expect(httpServer.close).toHaveBeenCalled()
71
-
72
- httpServer.close.mock.calls[0][0]?.() // `close` callback
73
-
74
- await stopped
20
+ expect(server.connected).toBeTruthy()
21
+ expect(server.port).toBeGreaterThan(0)
75
22
  })
76
23
 
77
24
  it('should register request handler', async () => {
78
- const process = jest.fn(async () => ({})) as unknown as Processing
79
- const req = createRequest()
25
+ const process: Processing = jest.fn().mockResolvedValue(undefined)
80
26
 
81
27
  server.attach(process)
82
28
 
83
- await use(req)
29
+ const res = await fetch(`http://localhost:${server.port}`)
30
+
31
+ await res.text()
84
32
 
85
- expect(process).toHaveBeenCalled()
33
+ expect(process).toHaveBeenCalledTimes(1)
86
34
  })
87
35
 
88
36
  it('should send 501 on unknown method', async () => {
89
- const req = createRequest({ method: generate() })
37
+ const head = await fetch(`http://localhost:${server.port}/`, { method: 'COPY' })
90
38
 
91
- await use(req)
39
+ await head.text()
40
+ expect(head.status).toBe(501)
41
+ })
92
42
 
93
- expect(res.sendStatus).toHaveBeenCalledWith(501)
43
+ it('should stop HTTP server', async () => {
44
+ await server.disconnect()
45
+ expect(server.port).toBe(0)
46
+ expect(server.connected).toBeFalsy()
94
47
  })
95
48
 
96
49
  describe('result', () => {
97
- it('should send status code 200 if the result has a value', async () => {
98
- const req = createRequest()
50
+ beforeEach(async () => {
51
+ server = Server.create({ port: 0 })
52
+ await server.connect()
53
+ })
54
+
55
+ afterEach(async () => {
56
+ await server.disconnect()
57
+ })
99
58
 
59
+ it('should send status code 200 if the result has a value', async () => {
100
60
  server.attach(async (): Promise<OutgoingMessage> => ({
101
- headers: new Headers(), body: generate()
61
+ headers: new Headers(), body: randomUUID()
102
62
  }))
103
- await use(req)
104
63
 
105
- expect(res.status).toHaveBeenCalledWith(200)
64
+ const res = await fetch(`http://localhost:${server.port}/`)
65
+
66
+ await res.text()
67
+ expect(res.status).toBe(200)
106
68
  })
107
69
 
108
70
  it('should send status code 204 if the result has no value', async () => {
109
- const req = createRequest()
110
-
111
71
  server.attach(async (): Promise<OutgoingMessage> => ({ headers: new Headers() }))
112
- await use(req)
113
72
 
114
- expect(res.status).toHaveBeenCalledWith(204)
73
+ const res = await fetch(`http://localhost:${server.port}/`)
74
+
75
+ await res.text()
76
+ expect(res.status).toBe(204)
115
77
  })
116
78
 
117
79
  it('should send result', async () => {
118
- const body = { [generate()]: generate() }
119
- const json = JSON.stringify(body)
120
- const buf = Buffer.from(json)
121
- const req = createRequest({ headers: { accept: 'application/json' } })
80
+ const body = { [randomUUID()]: randomUUID() }
122
81
 
123
- server.attach(async (): Promise<OutgoingMessage> => ({ headers: new Headers(), body }))
124
- await use(req)
82
+ server.attach(async (): Promise<OutgoingMessage> =>
83
+ ({ headers: new Headers(), body }))
125
84
 
126
- expect(res.end).toHaveBeenCalledWith(buf)
127
- })
85
+ const res = await fetch(`http://localhost:${server.port}/`,
86
+ { headers: { accept: 'application/json' } })
128
87
 
129
- it('should return 500 on exception', async () => {
130
- async function process (): Promise<OutgoingMessage> {
131
- throw new Error('Bad')
132
- }
88
+ const result = await res.json()
133
89
 
134
- const req = createRequest()
135
-
136
- server.attach(process)
137
- await use(req)
138
-
139
- expect(res.status).toHaveBeenCalledWith(500)
90
+ expect(result).toEqual(body)
140
91
  })
141
92
 
142
- it('should output exception message if debug is enabled', async () => {
143
- jest.clearAllMocks()
144
-
145
- server = Server.create({ debug: true })
146
- app = express.mock.results[0]?.value
147
-
148
- const message = generate()
149
- const req = createRequest()
150
-
151
- async function process (): Promise<OutgoingMessage> {
152
- throw new Error(message)
153
- }
93
+ it('should return 500 on exception', async () => {
94
+ server.attach(jest.fn().mockRejectedValue(new Error('Bad')))
154
95
 
155
- server.attach(process)
156
- await use(req)
96
+ const res = await fetch(`http://localhost:${server.port}/`)
157
97
 
158
- expect(res.status).toHaveBeenCalledWith(500)
98
+ await res.text()
99
+ expect(res.status).toBe(500)
159
100
  })
160
101
 
161
102
  it('should send client error', async () => {
162
- const req = createRequest()
163
- const message = generate()
103
+ const message = randomUUID()
164
104
 
165
- async function process (): Promise<OutgoingMessage> {
166
- throw new BadRequest(message)
167
- }
105
+ server.attach(jest.fn().mockRejectedValueOnce(new BadRequest(message)))
168
106
 
169
- server.attach(process)
170
- await use(req)
107
+ const res = await fetch(`http://localhost:${server.port}/`)
108
+ const text = await res.text()
171
109
 
172
- expect(res.status).toHaveBeenCalledWith(400)
110
+ expect(res.status).toBe(400)
111
+ expect(text).toContain(message)
173
112
  })
174
113
  })
175
114
 
176
115
  describe('options', () => {
177
116
  it('should send 501 on unspecified method', async () => {
178
- jest.clearAllMocks()
117
+ server = Server.create({ methods: new Set(['COPY']), port: 0 })
118
+ await server.connect()
179
119
 
180
- server = Server.create({ methods: new Set(['COPY']) })
181
- app = express.mock.results[0]?.value
120
+ const res = await fetch(`http://localhost:${server.port}/`)
182
121
 
183
- const req = createRequest({ method: 'GET' })
184
-
185
- await use(req)
186
-
187
- expect(res.sendStatus).toHaveBeenCalledWith(501)
122
+ await res.text()
123
+ await server.disconnect()
124
+ expect(res.status).toBe(501)
188
125
  })
189
126
  })
190
-
191
- async function use (req: Request): Promise<void> {
192
- for (const call of app.use.mock.calls) {
193
- const usage = call[0] as unknown as RequestHandler
194
-
195
- usage(req, res, next)
196
- }
197
-
198
- await immediate()
199
- }
@@ -1,52 +1,67 @@
1
+ import fs from 'node:fs'
2
+ import os from 'node:os'
1
3
  import express from 'express'
2
- import cors from 'cors'
3
4
  import { Connector } from '@toa.io/core'
4
5
  import { promex } from '@toa.io/generic'
5
6
  import Negotiator from 'negotiator'
6
7
  import { read, write, type IncomingMessage, type OutgoingMessage } from './messages'
7
8
  import { ClientError, Exception } from './exceptions'
8
9
  import { formats, types } from './formats'
9
- import type { Format } from './formats'
10
10
  import type * as http from 'node:http'
11
11
  import type { Express, Request, Response, NextFunction } from 'express'
12
12
 
13
13
  export class Server extends Connector {
14
- private readonly debug: boolean
15
- private readonly app: Express
16
14
  private server?: http.Server
15
+ private readonly app: Express
16
+ private readonly debug: boolean
17
+ private readonly requestedPort: number
17
18
 
18
- private constructor (app: Express, debug: boolean) {
19
+ private constructor (app: Express, debug: boolean, port: number) {
19
20
  super()
20
21
 
21
22
  this.app = app
22
23
  this.debug = debug
24
+ this.requestedPort = port
25
+ }
26
+
27
+ public get port (): number {
28
+ if (this.server === undefined) return this.requestedPort
29
+
30
+ const address = this.server.address()
31
+
32
+ if (address === null || typeof address === 'string')
33
+ throw new Error('Server is not listening on a port.')
34
+
35
+ return address.port
23
36
  }
24
37
 
25
- public static create (options: Partial<Properties> = {}): Server {
26
- const properties: Properties = Object.assign({}, defaults(), options)
38
+ public static create (options?: Partial<Properties>): Server {
39
+ const properties = options === undefined
40
+ ? DEFAULTS
41
+ : { ...DEFAULTS, ...options }
27
42
 
28
43
  const app = express()
29
44
 
30
45
  app.disable('x-powered-by')
31
- app.use(cors({ allowedHeaders: ['content-type'] }))
32
46
  app.use(supportedMethods(properties.methods))
33
47
 
34
- return new Server(app, properties.debug)
48
+ return new Server(app, properties.debug, properties.port)
35
49
  }
36
50
 
37
51
  public attach (process: Processing): void {
38
- this.app.use((request: any, response: Response): void => {
39
- this.extend(request)
40
- .then(process)
41
- .then(this.success(request, response))
42
- .catch(this.fail(request, response))
52
+ this.app.use((request: Request, response: Response) => {
53
+ const message = this.extend(request)
54
+
55
+ process(message)
56
+ .then(this.success(message, response))
57
+ .catch(this.fail(message, response))
43
58
  })
44
59
  }
45
60
 
46
61
  protected override async open (): Promise<void> {
47
62
  const listening = promex()
48
63
 
49
- this.server = this.app.listen(8000, listening.callback)
64
+ this.server = this.app.listen(this.requestedPort, listening.callback)
50
65
 
51
66
  await listening
52
67
 
@@ -59,17 +74,27 @@ export class Server extends Connector {
59
74
  this.server?.close(stopped.callback)
60
75
 
61
76
  await stopped
62
- }
63
77
 
64
- protected override dispose (): void {
78
+ this.server = undefined
79
+
65
80
  console.info('HTTP Server has been stopped.')
66
81
  }
67
82
 
68
- private async extend (request: IncomingMessage): Promise<IncomingMessage> {
69
- const message = request as unknown as IncomingMessage
83
+ private extend (request: Request): IncomingMessage {
84
+ const message = request as IncomingMessage
85
+
86
+ negotiate(request, message)
87
+
88
+ message.pipelines = { body: [], response: [] }
89
+
90
+ message.parse = async <T> (): Promise<T> => {
91
+ const value = await read(request)
70
92
 
71
- message.encoder = negotiate(request)
72
- message.parse = async <T> (): Promise<T> => await read(request)
93
+ if (message.pipelines.body.length === 0)
94
+ return value
95
+
96
+ return message.pipelines.body.reduce((value, transform) => transform(value), value)
97
+ }
73
98
 
74
99
  return message
75
100
  }
@@ -85,37 +110,30 @@ export class Server extends Connector {
85
110
  else status = 200
86
111
 
87
112
  response.status(status)
88
- message.headers?.forEach((value, key) => response.set(key, value))
89
-
90
- if (message.body !== undefined && message.body !== null)
91
- write(request, response, message)
92
- else
93
- response.end()
113
+ write(request, response, message)
94
114
  }
95
115
  }
96
116
 
97
117
  private fail (request: IncomingMessage, response: Response) {
98
- return (exception: Error) => {
118
+ return async (exception: Error) => {
119
+ if (!request.complete)
120
+ await adam(request)
121
+
99
122
  const status = exception instanceof Exception
100
123
  ? exception.status
101
124
  : 500
102
125
 
103
126
  response.status(status)
104
127
 
105
- const outputAllowed = exception instanceof ClientError || this.debug
128
+ const message: OutgoingMessage = {}
129
+ const verbose = exception instanceof ClientError || this.debug
106
130
 
107
- if (outputAllowed) {
108
- const body = exception instanceof Exception
131
+ if (verbose)
132
+ message.body = exception instanceof Exception
109
133
  ? exception.body
110
134
  : (exception.stack ?? exception.message)
111
135
 
112
- write(request, response, { body })
113
- } else
114
- response.end()
115
-
116
- // stop accepting request
117
- if (!request.complete)
118
- request.destroy()
136
+ write(request, response, message)
119
137
  }
120
138
  }
121
139
  }
@@ -127,23 +145,49 @@ function supportedMethods (methods: Set<string>) {
127
145
  }
128
146
  }
129
147
 
130
- function negotiate (request: Request): Format | null {
148
+ function negotiate (request: Request, message: IncomingMessage): void {
149
+ if (request.headers.accept !== undefined) {
150
+ const match = SUBTYPE.exec(request.headers.accept)
151
+
152
+ if (match !== null) {
153
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
154
+ const { type, subtype, suffix } = match.groups!
155
+
156
+ request.headers.accept = `${type}/${suffix}`
157
+ message.subtype = subtype
158
+ }
159
+ }
160
+
131
161
  const negotiator = new Negotiator(request)
132
162
  const mediaType = negotiator.mediaType(types)
133
163
 
134
- return mediaType === undefined ? null : formats[mediaType]
164
+ message.encoder = mediaType === undefined ? null : formats[mediaType]
165
+ }
166
+
167
+ // https://github.com/whatwg/fetch/issues/1254
168
+ async function adam (request: Request): Promise<void> {
169
+ const completed = promex()
170
+ const devnull = fs.createWriteStream(os.devNull)
171
+
172
+ request
173
+ .on('end', completed.callback)
174
+ .pipe(devnull)
175
+
176
+ return await completed
177
+ }
178
+
179
+ const DEFAULTS: Properties = {
180
+ methods: new Set<string>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']),
181
+ debug: false,
182
+ port: 8000
135
183
  }
136
184
 
137
185
  interface Properties {
138
186
  methods: Set<string>
139
187
  debug: boolean
140
- }
141
-
142
- function defaults (): Properties {
143
- return {
144
- methods: new Set<string>(['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']),
145
- debug: false
146
- }
188
+ port: number
147
189
  }
148
190
 
149
191
  export type Processing = (input: IncomingMessage) => Promise<OutgoingMessage>
192
+
193
+ const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/