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

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 (449) 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 +100 -0
  20. package/components/identity.federation/operations/authenticate.d.ts +3 -0
  21. package/components/identity.federation/operations/authenticate.js +20 -0
  22. package/components/identity.federation/operations/authenticate.js.map +1 -0
  23. package/components/identity.federation/operations/create.d.ts +10 -0
  24. package/components/identity.federation/operations/create.js +15 -0
  25. package/components/identity.federation/operations/create.js.map +1 -0
  26. package/components/identity.federation/operations/lib/assertions-as-values.d.ts +4 -0
  27. package/components/identity.federation/operations/lib/assertions-as-values.js +45 -0
  28. package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -0
  29. package/components/identity.federation/operations/lib/jwt.d.ts +20 -0
  30. package/components/identity.federation/operations/lib/jwt.js +136 -0
  31. package/components/identity.federation/operations/lib/jwt.js.map +1 -0
  32. package/components/identity.federation/operations/schemas.d.ts +59 -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/authenticate.ts +28 -0
  40. package/components/identity.federation/source/create.ts +26 -0
  41. package/components/identity.federation/source/lib/assertions-as-values.ts +19 -0
  42. package/components/identity.federation/source/lib/jwt.test.ts +56 -0
  43. package/components/identity.federation/source/lib/jwt.ts +171 -0
  44. package/components/identity.federation/source/schemas.ts +61 -0
  45. package/components/identity.federation/source/types.ts +56 -0
  46. package/components/identity.federation/tsconfig.json +9 -0
  47. package/components/identity.roles/operations/list.d.ts +5 -0
  48. package/components/identity.roles/operations/list.js +8 -0
  49. package/components/identity.roles/operations/list.js.map +1 -0
  50. package/components/identity.roles/operations/principal.d.ts +15 -0
  51. package/components/identity.roles/operations/principal.js +8 -0
  52. package/components/identity.roles/operations/principal.js.map +1 -0
  53. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -0
  54. package/components/identity.tokens/manifest.toa.yaml +1 -1
  55. package/components/identity.tokens/operations/authenticate.d.ts +9 -0
  56. package/components/identity.tokens/operations/authenticate.js +32 -0
  57. package/components/identity.tokens/operations/authenticate.js.map +1 -0
  58. package/components/identity.tokens/operations/decrypt.d.ts +3 -0
  59. package/components/identity.tokens/operations/decrypt.js +32 -0
  60. package/components/identity.tokens/operations/decrypt.js.map +1 -0
  61. package/components/identity.tokens/operations/encrypt.d.ts +8 -0
  62. package/components/identity.tokens/operations/encrypt.js +22 -0
  63. package/components/identity.tokens/operations/encrypt.js.map +1 -0
  64. package/components/identity.tokens/operations/revoke.d.ts +2 -0
  65. package/components/identity.tokens/operations/revoke.js +8 -0
  66. package/components/identity.tokens/operations/revoke.js.map +1 -0
  67. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -0
  68. package/components/identity.tokens/operations/types.d.ts +40 -0
  69. package/components/identity.tokens/operations/types.js +3 -0
  70. package/components/identity.tokens/operations/types.js.map +1 -0
  71. package/components/octets.storage/manifest.toa.yaml +1 -0
  72. package/components/octets.storage/operations/store.js +2 -2
  73. package/cucumber.js +0 -1
  74. package/documentation/components.md +32 -2
  75. package/documentation/identity.md +14 -7
  76. package/documentation/octets.md +105 -40
  77. package/documentation/protocol.md +21 -1
  78. package/documentation/query.md +1 -1
  79. package/documentation/vary.md +69 -0
  80. package/features/cors.feature +72 -0
  81. package/features/identity.feature +19 -3
  82. package/features/identity.federation.feature +155 -0
  83. package/features/octets.entries.feature +121 -0
  84. package/features/octets.feature +2 -28
  85. package/features/octets.meta.feature +65 -0
  86. package/features/octets.workflows.feature +176 -4
  87. package/features/response.feature +65 -0
  88. package/features/routes.feature +37 -0
  89. package/features/steps/Captures.ts +6 -0
  90. package/features/steps/Components.ts +18 -6
  91. package/features/steps/Gateway.ts +1 -2
  92. package/features/steps/HTTP.ts +40 -87
  93. package/features/steps/IdP.ts +149 -0
  94. package/features/steps/Parameters.ts +8 -2
  95. package/features/steps/Workspace.ts +5 -7
  96. package/features/steps/components/echo/operations/error.js +11 -0
  97. package/features/steps/components/octets.tester/manifest.toa.yaml +3 -0
  98. package/features/steps/components/octets.tester/operations/concat.js +7 -0
  99. package/features/steps/components/octets.tester/operations/echo.js +7 -0
  100. package/features/steps/components/users/manifest.toa.yaml +3 -0
  101. package/features/steps/components/users.properties/manifest.toa.yaml +13 -0
  102. package/features/steps/tsconfig.json +1 -1
  103. package/features/vary.feature +150 -0
  104. package/package.json +17 -18
  105. package/schemas/octets/delete.cos.yaml +2 -1
  106. package/schemas/octets/list.cos.yaml +2 -1
  107. package/schemas/octets/workflow.cos.yaml +12 -0
  108. package/source/Directive.test.ts +8 -2
  109. package/source/Directive.ts +19 -16
  110. package/source/Factory.ts +8 -7
  111. package/source/Gateway.ts +22 -8
  112. package/source/HTTP/Server.fixtures.ts +0 -1
  113. package/source/HTTP/Server.test.ts +61 -134
  114. package/source/HTTP/Server.ts +91 -47
  115. package/source/HTTP/formats/msgpack.ts +9 -6
  116. package/source/HTTP/formats/text.ts +1 -1
  117. package/source/HTTP/formats/yaml.ts +1 -1
  118. package/source/HTTP/messages.ts +15 -3
  119. package/source/Interception.ts +24 -0
  120. package/source/RTD/Directives.ts +2 -2
  121. package/source/RTD/Tree.ts +3 -0
  122. package/source/RTD/syntax/parse.ts +6 -6
  123. package/source/RTD/syntax/types.ts +1 -1
  124. package/source/deployment.ts +1 -2
  125. package/source/directives/auth/{Family.ts → Authorization.ts} +29 -33
  126. package/source/directives/auth/Incept.ts +1 -1
  127. package/source/directives/auth/Rule.ts +2 -2
  128. package/source/directives/auth/index.ts +2 -2
  129. package/source/directives/auth/schemes.ts +2 -1
  130. package/source/directives/auth/types.ts +9 -6
  131. package/source/directives/cache/{Family.ts → Cache.ts} +4 -5
  132. package/source/directives/cache/index.ts +2 -2
  133. package/source/directives/cache/types.ts +1 -1
  134. package/source/directives/cors/CORS.ts +54 -0
  135. package/source/directives/cors/index.ts +3 -0
  136. package/source/directives/dev/{Family.ts → Development.ts} +3 -4
  137. package/source/directives/dev/Stub.ts +4 -4
  138. package/source/directives/dev/Throw.ts +4 -4
  139. package/source/directives/dev/index.ts +2 -2
  140. package/source/directives/dev/types.ts +1 -1
  141. package/source/directives/index.ts +10 -6
  142. package/source/directives/octets/Context.ts +1 -1
  143. package/source/directives/octets/Delete.ts +50 -9
  144. package/source/directives/octets/Fetch.ts +18 -19
  145. package/source/directives/octets/List.ts +37 -7
  146. package/source/directives/octets/{Family.ts → Octets.ts} +10 -7
  147. package/source/directives/octets/Permute.ts +3 -3
  148. package/source/directives/octets/Store.ts +57 -99
  149. package/source/directives/octets/Workflow.ts +41 -0
  150. package/source/directives/octets/index.ts +2 -2
  151. package/source/directives/octets/schemas.test.ts +21 -0
  152. package/source/directives/octets/schemas.ts +13 -6
  153. package/source/directives/octets/types.ts +4 -3
  154. package/source/directives/octets/workflows/Execution.ts +76 -0
  155. package/source/directives/octets/workflows/Workflow.ts +37 -0
  156. package/source/directives/octets/workflows/index.ts +1 -0
  157. package/source/directives/vary/Directive.ts +6 -0
  158. package/source/directives/vary/Embed.ts +62 -0
  159. package/source/directives/vary/Properties.ts +17 -0
  160. package/source/directives/vary/Vary.ts +48 -0
  161. package/source/directives/vary/embeddings/Embedding.ts +6 -0
  162. package/source/directives/vary/embeddings/Header.ts +30 -0
  163. package/source/directives/vary/embeddings/Language.ts +31 -0
  164. package/source/directives/vary/embeddings/index.ts +11 -0
  165. package/source/directives/vary/index.ts +3 -0
  166. package/source/io.ts +4 -0
  167. package/source/manifest.test.ts +6 -14
  168. package/source/manifest.ts +9 -6
  169. package/source/schemas.ts +7 -3
  170. package/transpiled/Annotation.d.ts +7 -0
  171. package/transpiled/Annotation.js +3 -0
  172. package/transpiled/Annotation.js.map +1 -0
  173. package/transpiled/Branch.d.ts +7 -0
  174. package/transpiled/Branch.js +3 -0
  175. package/transpiled/Branch.js.map +1 -0
  176. package/transpiled/Composition.d.ts +14 -0
  177. package/transpiled/Composition.js +43 -0
  178. package/transpiled/Composition.js.map +1 -0
  179. package/transpiled/Context.d.ts +5 -0
  180. package/transpiled/Context.js +3 -0
  181. package/transpiled/Context.js.map +1 -0
  182. package/transpiled/Directive.d.ts +31 -0
  183. package/transpiled/Directive.js +78 -0
  184. package/transpiled/Directive.js.map +1 -0
  185. package/transpiled/Endpoint.d.ts +20 -0
  186. package/transpiled/Endpoint.js +45 -0
  187. package/transpiled/Endpoint.js.map +1 -0
  188. package/transpiled/Factory.d.ts +9 -0
  189. package/transpiled/Factory.js +67 -0
  190. package/transpiled/Factory.js.map +1 -0
  191. package/transpiled/Gateway.d.ts +22 -0
  192. package/transpiled/Gateway.js +102 -0
  193. package/transpiled/Gateway.js.map +1 -0
  194. package/transpiled/HTTP/Server.d.ts +24 -0
  195. package/transpiled/HTTP/Server.fixtures.d.ts +10 -0
  196. package/transpiled/HTTP/Server.fixtures.js +31 -0
  197. package/transpiled/HTTP/Server.fixtures.js.map +1 -0
  198. package/transpiled/HTTP/Server.js +149 -0
  199. package/transpiled/HTTP/Server.js.map +1 -0
  200. package/transpiled/HTTP/exceptions.d.ts +34 -0
  201. package/transpiled/HTTP/exceptions.js +71 -0
  202. package/transpiled/HTTP/exceptions.js.map +1 -0
  203. package/transpiled/HTTP/formats/index.d.ts +10 -0
  204. package/transpiled/HTTP/formats/index.js +38 -0
  205. package/transpiled/HTTP/formats/index.js.map +1 -0
  206. package/transpiled/HTTP/formats/json.d.ts +6 -0
  207. package/transpiled/HTTP/formats/json.js +17 -0
  208. package/transpiled/HTTP/formats/json.js.map +1 -0
  209. package/transpiled/HTTP/formats/msgpack.d.ts +6 -0
  210. package/transpiled/HTTP/formats/msgpack.js +17 -0
  211. package/transpiled/HTTP/formats/msgpack.js.map +1 -0
  212. package/transpiled/HTTP/formats/text.d.ts +8 -0
  213. package/transpiled/HTTP/formats/text.js +15 -0
  214. package/transpiled/HTTP/formats/text.js.map +1 -0
  215. package/transpiled/HTTP/formats/yaml.d.ts +6 -0
  216. package/transpiled/HTTP/formats/yaml.js +41 -0
  217. package/transpiled/HTTP/formats/yaml.js.map +1 -0
  218. package/transpiled/HTTP/index.d.ts +3 -0
  219. package/transpiled/HTTP/index.js +20 -0
  220. package/transpiled/HTTP/index.js.map +1 -0
  221. package/transpiled/HTTP/messages.d.ts +33 -0
  222. package/transpiled/HTTP/messages.js +75 -0
  223. package/transpiled/HTTP/messages.js.map +1 -0
  224. package/transpiled/Interception.d.ts +9 -0
  225. package/transpiled/Interception.js +19 -0
  226. package/transpiled/Interception.js.map +1 -0
  227. package/transpiled/Mapping.d.ts +8 -0
  228. package/transpiled/Mapping.js +38 -0
  229. package/transpiled/Mapping.js.map +1 -0
  230. package/transpiled/Query.d.ts +13 -0
  231. package/transpiled/Query.js +107 -0
  232. package/transpiled/Query.js.map +1 -0
  233. package/transpiled/RTD/Context.d.ts +11 -0
  234. package/transpiled/RTD/Context.js +3 -0
  235. package/transpiled/RTD/Context.js.map +1 -0
  236. package/transpiled/RTD/Directives.d.ts +7 -0
  237. package/transpiled/RTD/Directives.js +3 -0
  238. package/transpiled/RTD/Directives.js.map +1 -0
  239. package/transpiled/RTD/Endpoint.d.ts +9 -0
  240. package/transpiled/RTD/Endpoint.js +3 -0
  241. package/transpiled/RTD/Endpoint.js.map +1 -0
  242. package/transpiled/RTD/Match.d.ts +11 -0
  243. package/transpiled/RTD/Match.js +3 -0
  244. package/transpiled/RTD/Match.js.map +1 -0
  245. package/transpiled/RTD/Method.d.ts +9 -0
  246. package/transpiled/RTD/Method.js +16 -0
  247. package/transpiled/RTD/Method.js.map +1 -0
  248. package/transpiled/RTD/Node.d.ts +21 -0
  249. package/transpiled/RTD/Node.js +61 -0
  250. package/transpiled/RTD/Node.js.map +1 -0
  251. package/transpiled/RTD/Route.d.ts +14 -0
  252. package/transpiled/RTD/Route.js +49 -0
  253. package/transpiled/RTD/Route.js.map +1 -0
  254. package/transpiled/RTD/Tree.d.ts +14 -0
  255. package/transpiled/RTD/Tree.js +42 -0
  256. package/transpiled/RTD/Tree.js.map +1 -0
  257. package/transpiled/RTD/factory.d.ts +6 -0
  258. package/transpiled/RTD/factory.js +36 -0
  259. package/transpiled/RTD/factory.js.map +1 -0
  260. package/transpiled/RTD/index.d.ts +8 -0
  261. package/transpiled/RTD/index.js +38 -0
  262. package/transpiled/RTD/index.js.map +1 -0
  263. package/transpiled/RTD/segment.d.ts +8 -0
  264. package/transpiled/RTD/segment.js +25 -0
  265. package/transpiled/RTD/segment.js.map +1 -0
  266. package/transpiled/RTD/syntax/index.d.ts +2 -0
  267. package/transpiled/RTD/syntax/index.js +19 -0
  268. package/transpiled/RTD/syntax/index.js.map +1 -0
  269. package/transpiled/RTD/syntax/parse.d.ts +4 -0
  270. package/transpiled/RTD/syntax/parse.js +128 -0
  271. package/transpiled/RTD/syntax/parse.js.map +1 -0
  272. package/transpiled/RTD/syntax/types.d.ts +41 -0
  273. package/transpiled/RTD/syntax/types.js +5 -0
  274. package/transpiled/RTD/syntax/types.js.map +1 -0
  275. package/transpiled/Remotes.d.ts +9 -0
  276. package/transpiled/Remotes.js +25 -0
  277. package/transpiled/Remotes.js.map +1 -0
  278. package/transpiled/Tenant.d.ts +13 -0
  279. package/transpiled/Tenant.js +34 -0
  280. package/transpiled/Tenant.js.map +1 -0
  281. package/transpiled/deployment.d.ts +3 -0
  282. package/transpiled/deployment.js +66 -0
  283. package/transpiled/deployment.js.map +1 -0
  284. package/transpiled/directives/auth/Anonymous.d.ts +6 -0
  285. package/transpiled/directives/auth/Anonymous.js +17 -0
  286. package/transpiled/directives/auth/Anonymous.js.map +1 -0
  287. package/transpiled/directives/auth/Authorization.d.ts +20 -0
  288. package/transpiled/directives/auth/Authorization.js +125 -0
  289. package/transpiled/directives/auth/Authorization.js.map +1 -0
  290. package/transpiled/directives/auth/Echo.d.ts +6 -0
  291. package/transpiled/directives/auth/Echo.js +13 -0
  292. package/transpiled/directives/auth/Echo.js.map +1 -0
  293. package/transpiled/directives/auth/Id.d.ts +7 -0
  294. package/transpiled/directives/auth/Id.js +17 -0
  295. package/transpiled/directives/auth/Id.js.map +1 -0
  296. package/transpiled/directives/auth/Incept.d.ts +10 -0
  297. package/transpiled/directives/auth/Incept.js +58 -0
  298. package/transpiled/directives/auth/Incept.js.map +1 -0
  299. package/transpiled/directives/auth/Role.d.ts +11 -0
  300. package/transpiled/directives/auth/Role.js +44 -0
  301. package/transpiled/directives/auth/Role.js.map +1 -0
  302. package/transpiled/directives/auth/Rule.d.ts +9 -0
  303. package/transpiled/directives/auth/Rule.js +22 -0
  304. package/transpiled/directives/auth/Rule.js.map +1 -0
  305. package/transpiled/directives/auth/Scheme.d.ts +7 -0
  306. package/transpiled/directives/auth/Scheme.js +47 -0
  307. package/transpiled/directives/auth/Scheme.js.map +1 -0
  308. package/transpiled/directives/auth/index.d.ts +2 -0
  309. package/transpiled/directives/auth/index.js +6 -0
  310. package/transpiled/directives/auth/index.js.map +1 -0
  311. package/transpiled/directives/auth/schemes.d.ts +3 -0
  312. package/transpiled/directives/auth/schemes.js +10 -0
  313. package/transpiled/directives/auth/schemes.js.map +1 -0
  314. package/transpiled/directives/auth/split.d.ts +2 -0
  315. package/transpiled/directives/auth/split.js +38 -0
  316. package/transpiled/directives/auth/split.js.map +1 -0
  317. package/transpiled/directives/auth/types.d.ts +31 -0
  318. package/transpiled/directives/auth/types.js +3 -0
  319. package/transpiled/directives/auth/types.js.map +1 -0
  320. package/transpiled/directives/cache/Cache.d.ts +11 -0
  321. package/transpiled/directives/cache/Cache.js +28 -0
  322. package/transpiled/directives/cache/Cache.js.map +1 -0
  323. package/transpiled/directives/cache/Control.d.ts +9 -0
  324. package/transpiled/directives/cache/Control.js +42 -0
  325. package/transpiled/directives/cache/Control.js.map +1 -0
  326. package/transpiled/directives/cache/Exact.d.ts +4 -0
  327. package/transpiled/directives/cache/Exact.js +11 -0
  328. package/transpiled/directives/cache/Exact.js.map +1 -0
  329. package/transpiled/directives/cache/index.d.ts +2 -0
  330. package/transpiled/directives/cache/index.js +6 -0
  331. package/transpiled/directives/cache/index.js.map +1 -0
  332. package/transpiled/directives/cache/types.d.ts +7 -0
  333. package/transpiled/directives/cache/types.js +3 -0
  334. package/transpiled/directives/cache/types.js.map +1 -0
  335. package/transpiled/directives/cors/CORS.d.ts +11 -0
  336. package/transpiled/directives/cors/CORS.js +44 -0
  337. package/transpiled/directives/cors/CORS.js.map +1 -0
  338. package/transpiled/directives/cors/index.d.ts +2 -0
  339. package/transpiled/directives/cors/index.js +6 -0
  340. package/transpiled/directives/cors/index.js.map +1 -0
  341. package/transpiled/directives/dev/Development.d.ts +9 -0
  342. package/transpiled/directives/dev/Development.js +29 -0
  343. package/transpiled/directives/dev/Development.js.map +1 -0
  344. package/transpiled/directives/dev/Stub.d.ts +7 -0
  345. package/transpiled/directives/dev/Stub.js +14 -0
  346. package/transpiled/directives/dev/Stub.js.map +1 -0
  347. package/transpiled/directives/dev/Throw.d.ts +7 -0
  348. package/transpiled/directives/dev/Throw.js +14 -0
  349. package/transpiled/directives/dev/Throw.js.map +1 -0
  350. package/transpiled/directives/dev/index.d.ts +2 -0
  351. package/transpiled/directives/dev/index.js +6 -0
  352. package/transpiled/directives/dev/index.js.map +1 -0
  353. package/transpiled/directives/dev/types.d.ts +4 -0
  354. package/transpiled/directives/dev/types.js +3 -0
  355. package/transpiled/directives/dev/types.js.map +1 -0
  356. package/transpiled/directives/index.d.ts +4 -0
  357. package/transpiled/directives/index.js +12 -0
  358. package/transpiled/directives/index.js.map +1 -0
  359. package/transpiled/directives/octets/Context.d.ts +8 -0
  360. package/transpiled/directives/octets/Context.js +40 -0
  361. package/transpiled/directives/octets/Context.js.map +1 -0
  362. package/transpiled/directives/octets/Delete.d.ts +19 -0
  363. package/transpiled/directives/octets/Delete.js +72 -0
  364. package/transpiled/directives/octets/Delete.js.map +1 -0
  365. package/transpiled/directives/octets/Fetch.d.ts +17 -0
  366. package/transpiled/directives/octets/Fetch.js +76 -0
  367. package/transpiled/directives/octets/Fetch.js.map +1 -0
  368. package/transpiled/directives/octets/List.d.ts +15 -0
  369. package/transpiled/directives/octets/List.js +65 -0
  370. package/transpiled/directives/octets/List.js.map +1 -0
  371. package/transpiled/directives/octets/Octets.d.ts +12 -0
  372. package/transpiled/directives/octets/Octets.js +53 -0
  373. package/transpiled/directives/octets/Octets.js.map +1 -0
  374. package/transpiled/directives/octets/Permute.d.ts +10 -0
  375. package/transpiled/directives/octets/Permute.js +51 -0
  376. package/transpiled/directives/octets/Permute.js.map +1 -0
  377. package/transpiled/directives/octets/Store.d.ts +23 -0
  378. package/transpiled/directives/octets/Store.js +88 -0
  379. package/transpiled/directives/octets/Store.js.map +1 -0
  380. package/transpiled/directives/octets/Workflow.d.ts +14 -0
  381. package/transpiled/directives/octets/Workflow.js +52 -0
  382. package/transpiled/directives/octets/Workflow.js.map +1 -0
  383. package/transpiled/directives/octets/index.d.ts +2 -0
  384. package/transpiled/directives/octets/index.js +6 -0
  385. package/transpiled/directives/octets/index.js.map +1 -0
  386. package/transpiled/directives/octets/schemas.d.ts +13 -0
  387. package/transpiled/directives/octets/schemas.js +18 -0
  388. package/transpiled/directives/octets/schemas.js.map +1 -0
  389. package/transpiled/directives/octets/types.d.ts +10 -0
  390. package/transpiled/directives/octets/types.js +3 -0
  391. package/transpiled/directives/octets/types.js.map +1 -0
  392. package/transpiled/directives/octets/workflows/Execution.d.ts +25 -0
  393. package/transpiled/directives/octets/workflows/Execution.js +54 -0
  394. package/transpiled/directives/octets/workflows/Execution.js.map +1 -0
  395. package/transpiled/directives/octets/workflows/Workflow.d.ts +12 -0
  396. package/transpiled/directives/octets/workflows/Workflow.js +25 -0
  397. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -0
  398. package/transpiled/directives/octets/workflows/index.d.ts +1 -0
  399. package/transpiled/directives/octets/workflows/index.js +6 -0
  400. package/transpiled/directives/octets/workflows/index.js.map +1 -0
  401. package/transpiled/directives/vary/Directive.d.ts +5 -0
  402. package/transpiled/directives/vary/Directive.js +3 -0
  403. package/transpiled/directives/vary/Directive.js.map +1 -0
  404. package/transpiled/directives/vary/Embed.d.ts +10 -0
  405. package/transpiled/directives/vary/Embed.js +49 -0
  406. package/transpiled/directives/vary/Embed.js.map +1 -0
  407. package/transpiled/directives/vary/Properties.d.ts +9 -0
  408. package/transpiled/directives/vary/Properties.js +16 -0
  409. package/transpiled/directives/vary/Properties.js.map +1 -0
  410. package/transpiled/directives/vary/Vary.d.ts +10 -0
  411. package/transpiled/directives/vary/Vary.js +36 -0
  412. package/transpiled/directives/vary/Vary.js.map +1 -0
  413. package/transpiled/directives/vary/embeddings/Embedding.d.ts +5 -0
  414. package/transpiled/directives/vary/embeddings/Embedding.js +3 -0
  415. package/transpiled/directives/vary/embeddings/Embedding.js.map +1 -0
  416. package/transpiled/directives/vary/embeddings/Header.d.ts +7 -0
  417. package/transpiled/directives/vary/embeddings/Header.js +26 -0
  418. package/transpiled/directives/vary/embeddings/Header.js.map +1 -0
  419. package/transpiled/directives/vary/embeddings/Language.d.ts +7 -0
  420. package/transpiled/directives/vary/embeddings/Language.js +28 -0
  421. package/transpiled/directives/vary/embeddings/Language.js.map +1 -0
  422. package/transpiled/directives/vary/embeddings/index.d.ts +5 -0
  423. package/transpiled/directives/vary/embeddings/index.js +10 -0
  424. package/transpiled/directives/vary/embeddings/index.js.map +1 -0
  425. package/transpiled/directives/vary/index.d.ts +2 -0
  426. package/transpiled/directives/vary/index.js +6 -0
  427. package/transpiled/directives/vary/index.js.map +1 -0
  428. package/transpiled/discovery.d.ts +1 -0
  429. package/transpiled/discovery.js +3 -0
  430. package/transpiled/discovery.js.map +1 -0
  431. package/transpiled/exceptions.d.ts +2 -0
  432. package/transpiled/exceptions.js +39 -0
  433. package/transpiled/exceptions.js.map +1 -0
  434. package/transpiled/index.d.ts +5 -0
  435. package/transpiled/index.js +12 -0
  436. package/transpiled/index.js.map +1 -0
  437. package/transpiled/io.d.ts +3 -0
  438. package/transpiled/io.js +3 -0
  439. package/transpiled/io.js.map +1 -0
  440. package/transpiled/manifest.d.ts +3 -0
  441. package/transpiled/manifest.js +66 -0
  442. package/transpiled/manifest.js.map +1 -0
  443. package/transpiled/root.d.ts +2 -0
  444. package/transpiled/root.js +39 -0
  445. package/transpiled/root.js.map +1 -0
  446. package/transpiled/schemas.d.ts +7 -0
  447. package/transpiled/schemas.js +14 -0
  448. package/transpiled/schemas.js.map +1 -0
  449. package/transpiled/tsconfig.tsbuildinfo +1 -0
@@ -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})$/
@@ -1,13 +1,16 @@
1
1
  import { type Buffer } from 'node:buffer'
2
- import * as msgpack from 'msgpackr'
3
-
4
- export const type = 'application/msgpack'
5
- export const multipart = 'multipart/msgpack'
2
+ import { pack, unpack } from 'msgpackr'
6
3
 
7
4
  export function decode (buffer: Buffer): any {
8
- return msgpack.decode(buffer)
5
+ return unpack(buffer)
9
6
  }
10
7
 
11
8
  export function encode (value: any): Buffer {
12
- return msgpack.encode(value)
9
+ if (typeof value === 'object' && value !== null)
10
+ Object.setPrototypeOf(value, null)
11
+
12
+ return pack(value)
13
13
  }
14
+
15
+ export const type = 'application/msgpack'
16
+ export const multipart = 'multipart/msgpack'
@@ -7,6 +7,6 @@ export function decode (buffer: Buffer): any {
7
7
  return buffer.toString()
8
8
  }
9
9
 
10
- export function encode (value: any): Buffer {
10
+ export function encode (value: { toString: () => string }): Buffer {
11
11
  return Buffer.from(value.toString())
12
12
  }
@@ -11,7 +11,7 @@ export function decode (buffer: Buffer): any {
11
11
  }
12
12
 
13
13
  export function encode (value: any): Buffer {
14
- const text = yaml.dump(value)
14
+ const text = yaml.dump(value, { lineWidth: -1, noRefs: true })
15
15
 
16
16
  return Buffer.from(text)
17
17
  }
@@ -9,6 +9,11 @@ import type { Format } from './formats'
9
9
 
10
10
  export function write
11
11
  (request: IncomingMessage, response: Response, message: OutgoingMessage): void {
12
+ for (const transform of request.pipelines.response)
13
+ transform(message)
14
+
15
+ message.headers?.forEach((value, key) => response.set(key, value))
16
+
12
17
  if (message.body instanceof Readable)
13
18
  stream(message, request, response)
14
19
  else
@@ -36,7 +41,7 @@ export async function read (request: Request): Promise<any> {
36
41
  }
37
42
 
38
43
  function send (message: OutgoingMessage, request: IncomingMessage, response: Response): void {
39
- if (message.body === undefined) {
44
+ if (message.body === undefined || message.body === null) {
40
45
  response.end()
41
46
 
42
47
  return
@@ -47,8 +52,10 @@ function send (message: OutgoingMessage, request: IncomingMessage, response: Res
47
52
 
48
53
  const buf = request.encoder.encode(message.body)
49
54
 
50
- response.set('content-type', request.encoder.type)
51
- response.end(buf)
55
+ response
56
+ .set('content-type', request.encoder.type)
57
+ .append('vary', 'accept')
58
+ .end(buf)
52
59
  }
53
60
 
54
61
  function stream
@@ -97,6 +104,11 @@ export interface IncomingMessage extends Request {
97
104
  query: Query
98
105
  parse: <T> () => Promise<T>
99
106
  encoder: Format | null
107
+ subtype: string | null
108
+ pipelines: {
109
+ body: Array<(input: unknown) => unknown>
110
+ response: Array<(output: OutgoingMessage) => void>
111
+ }
100
112
  }
101
113
 
102
114
  export interface OutgoingMessage {
@@ -0,0 +1,24 @@
1
+ import type { Input, Output } from './io'
2
+
3
+ export class Interception implements Interceptor {
4
+ private readonly interceptors: Interceptor[]
5
+
6
+ public constructor (interceptors: Interceptor[]) {
7
+ this.interceptors = interceptors
8
+ }
9
+
10
+ public async intercept (input: Input): Promise<Output> {
11
+ for (const interceptor of this.interceptors) {
12
+ const output = await interceptor.intercept(input)
13
+
14
+ if (output !== null)
15
+ return output
16
+ }
17
+
18
+ return null
19
+ }
20
+ }
21
+
22
+ export interface Interceptor {
23
+ intercept: (input: Input) => Output | Promise<Output>
24
+ }
@@ -1,7 +1,7 @@
1
1
  import type * as syntax from './syntax'
2
2
 
3
- export interface Directives<T = any> {
4
- merge: (directive: T) => void
3
+ export interface Directives<TDirective = any> {
4
+ merge: (directive: TDirective) => void
5
5
  }
6
6
 
7
7
  export interface DirectivesFactory<T = any> {
@@ -25,6 +25,9 @@ export class Tree<
25
25
  }
26
26
 
27
27
  public match (path: string): Match<TEndpoint, TDirectives> | null {
28
+ if (path === '/')
29
+ return { node: this.trunk, parameters: [] }
30
+
28
31
  const fragments = fragment(path)
29
32
 
30
33
  return this.trunk.match(fragments)
@@ -28,7 +28,7 @@ function parseNode (input: object, shortcuts?: Shortcuts): Node {
28
28
  }
29
29
 
30
30
  if (key[0] === '/') {
31
- const route = parseRoute(key, value, shortcuts)
31
+ const route = parseRoute(key, value as Node, shortcuts)
32
32
 
33
33
  node.routes.push(route)
34
34
 
@@ -36,7 +36,7 @@ function parseNode (input: object, shortcuts?: Shortcuts): Node {
36
36
  }
37
37
 
38
38
  if (verbs.has(key)) {
39
- const method = parseMethod(key, value, shortcuts)
39
+ const method = parseMethod(key, value as Mapping, shortcuts)
40
40
 
41
41
  node.methods.push(method)
42
42
 
@@ -65,7 +65,7 @@ export function createNode (): Node {
65
65
  }
66
66
  }
67
67
 
68
- function parseRoute (path: string, value: object, shortcuts?: Shortcuts): Route {
68
+ function parseRoute (path: string, value: Node, shortcuts?: Shortcuts): Route {
69
69
  const node = parse(value, shortcuts)
70
70
 
71
71
  return createRoute(path, node)
@@ -106,10 +106,10 @@ function parseQuery (mapping: any): void {
106
106
  return
107
107
 
108
108
  if (typeof query.limit === 'number')
109
- query.limit = expandRange(query.limit)
109
+ query.limit = expandRange(query.limit as number)
110
110
 
111
111
  if (typeof query.omit === 'number')
112
- query.omit = expandRange(query.omit)
112
+ query.omit = expandRange(query.omit as number)
113
113
  }
114
114
 
115
115
  function parseDirectives (mapping: Record<string, any>, shortcuts?: Shortcuts): Directive[] {
@@ -132,7 +132,7 @@ function parseDirectives (mapping: Record<string, any>, shortcuts?: Shortcuts):
132
132
 
133
133
  function parseDirective (key: string, value: any, shortcuts?: Shortcuts): Directive | null {
134
134
  if (shortcuts?.has(key) === true)
135
- key = shortcuts.get(key) as string
135
+ key = shortcuts.get(key)! // eslint-disable-line @typescript-eslint/no-non-null-assertion
136
136
 
137
137
  const match = key.match(DIRECTIVE_RX)
138
138
 
@@ -45,4 +45,4 @@ export interface Range {
45
45
  range: [number, number]
46
46
  }
47
47
 
48
- export const verbs = new Set<string>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])
48
+ export const verbs = new Set<string>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
@@ -27,8 +27,7 @@ export function deployment (_: unknown, annotation: Annotation | undefined): Dep
27
27
  }
28
28
 
29
29
  if (annotation?.['/'] !== undefined) {
30
- const node = { '/': annotation['/'] }
31
- const tree = parse(node, shortcuts)
30
+ const tree = parse(annotation['/'], shortcuts)
32
31
 
33
32
  service.variables.push({
34
33
  name: 'TOA_EXPOSITION',