@toa.io/extensions.exposition 1.0.0-alpha.8 → 1.0.0-alpha.81

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 (443) hide show
  1. package/components/context.toa.yaml +2 -2
  2. package/components/identity.bans/manifest.toa.yaml +15 -7
  3. package/components/identity.bans/operations/transit.d.ts +14 -0
  4. package/components/identity.bans/operations/transit.js +11 -0
  5. package/components/identity.bans/operations/transit.js.map +1 -0
  6. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
  7. package/components/identity.bans/source/transit.ts +21 -0
  8. package/components/identity.bans/tsconfig.json +9 -0
  9. package/components/identity.basic/manifest.toa.yaml +20 -11
  10. package/components/identity.basic/operations/authenticate.d.ts +5 -1
  11. package/components/identity.basic/operations/authenticate.js +5 -2
  12. package/components/identity.basic/operations/authenticate.js.map +1 -1
  13. package/components/identity.basic/operations/incept.d.ts +12 -0
  14. package/components/identity.basic/operations/incept.js +26 -0
  15. package/components/identity.basic/operations/incept.js.map +1 -0
  16. package/components/identity.basic/operations/transit.d.ts +4 -4
  17. package/components/identity.basic/operations/transit.js +5 -3
  18. package/components/identity.basic/operations/transit.js.map +1 -1
  19. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  20. package/components/identity.basic/operations/types.d.ts +8 -4
  21. package/components/identity.basic/source/authenticate.ts +16 -5
  22. package/components/identity.basic/source/incept.ts +38 -0
  23. package/components/identity.basic/source/transit.ts +8 -6
  24. package/components/identity.basic/source/types.ts +8 -4
  25. package/components/identity.federation/manifest.toa.yaml +32 -16
  26. package/components/identity.federation/operations/authenticate.d.ts +2 -2
  27. package/components/identity.federation/operations/authenticate.js +4 -11
  28. package/components/identity.federation/operations/authenticate.js.map +1 -1
  29. package/components/identity.federation/operations/incept.d.ts +11 -0
  30. package/components/identity.federation/operations/{create.js → incept.js} +6 -7
  31. package/components/identity.federation/operations/incept.js.map +1 -0
  32. package/components/identity.federation/operations/lib/assertions-as-values.js +4 -2
  33. package/components/identity.federation/operations/lib/assertions-as-values.js.map +1 -1
  34. package/components/identity.federation/operations/lib/jwt.d.ts +5 -5
  35. package/components/identity.federation/operations/lib/jwt.js +25 -12
  36. package/components/identity.federation/operations/lib/jwt.js.map +1 -1
  37. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  38. package/components/identity.federation/operations/types/configuration.d.ts +14 -0
  39. package/components/identity.federation/operations/types/configuration.js +3 -0
  40. package/components/identity.federation/operations/types/configuration.js.map +1 -0
  41. package/components/identity.federation/operations/{types.d.ts → types/context.d.ts} +15 -7
  42. package/components/identity.federation/operations/types/context.js +3 -0
  43. package/components/identity.federation/operations/types/context.js.map +1 -0
  44. package/components/identity.federation/operations/types/entity.d.ts +6 -0
  45. package/components/identity.federation/operations/types/entity.js +3 -0
  46. package/components/identity.federation/operations/types/entity.js.map +1 -0
  47. package/components/identity.federation/operations/types/index.d.ts +3 -0
  48. package/components/identity.federation/operations/types/index.js +20 -0
  49. package/components/identity.federation/operations/types/index.js.map +1 -0
  50. package/components/identity.federation/source/authenticate.ts +6 -19
  51. package/components/identity.federation/source/{create.ts → incept.ts} +10 -9
  52. package/components/identity.federation/source/lib/assertions-as-values.ts +5 -2
  53. package/components/identity.federation/source/lib/jwt.test.ts +123 -4
  54. package/components/identity.federation/source/lib/jwt.ts +36 -16
  55. package/components/identity.federation/source/types/configuration.ts +15 -0
  56. package/components/identity.federation/source/{types.ts → types/context.ts} +17 -6
  57. package/components/identity.federation/source/types/entity.ts +6 -0
  58. package/components/identity.federation/source/types/index.ts +3 -0
  59. package/components/identity.federation/tsconfig.json +5 -4
  60. package/components/identity.roles/manifest.toa.yaml +17 -8
  61. package/components/identity.roles/operations/grant.d.ts +10 -0
  62. package/components/identity.roles/operations/grant.js +21 -0
  63. package/components/identity.roles/operations/grant.js.map +1 -0
  64. package/components/identity.roles/operations/lib/Entity.d.ts +5 -0
  65. package/components/identity.roles/operations/lib/Entity.js +3 -0
  66. package/components/identity.roles/operations/lib/Entity.js.map +1 -0
  67. package/components/identity.roles/operations/list.d.ts +1 -4
  68. package/components/identity.roles/operations/list.js.map +1 -1
  69. package/components/identity.roles/operations/principal.d.ts +4 -6
  70. package/components/identity.roles/operations/principal.js +6 -1
  71. package/components/identity.roles/operations/principal.js.map +1 -1
  72. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  73. package/components/identity.roles/source/grant.ts +32 -0
  74. package/components/identity.roles/source/lib/Entity.ts +5 -0
  75. package/components/identity.roles/source/list.ts +2 -4
  76. package/components/identity.roles/source/principal.ts +10 -8
  77. package/components/identity.tokens/manifest.toa.yaml +19 -5
  78. package/components/identity.tokens/operations/authenticate.d.ts +2 -2
  79. package/components/identity.tokens/operations/authenticate.js +12 -5
  80. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  81. package/components/identity.tokens/operations/decrypt.js +1 -0
  82. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  83. package/components/identity.tokens/operations/encrypt.js +5 -1
  84. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  85. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  86. package/components/identity.tokens/operations/types.d.ts +8 -2
  87. package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
  88. package/components/identity.tokens/source/authenticate.test.ts +11 -4
  89. package/components/identity.tokens/source/authenticate.ts +14 -6
  90. package/components/identity.tokens/source/decrypt.test.ts +5 -3
  91. package/components/identity.tokens/source/decrypt.ts +9 -8
  92. package/components/identity.tokens/source/encrypt.test.ts +26 -2
  93. package/components/identity.tokens/source/encrypt.ts +5 -1
  94. package/components/identity.tokens/source/types.ts +9 -2
  95. package/components/octets.storage/manifest.toa.yaml +6 -7
  96. package/components/octets.storage/operations/get.js +2 -2
  97. package/components/octets.storage/operations/store.js +113 -3
  98. package/documentation/access.md +75 -38
  99. package/documentation/authorities.md +49 -0
  100. package/documentation/cache.md +8 -1
  101. package/documentation/components.md +47 -22
  102. package/documentation/flow.md +31 -0
  103. package/documentation/identity.md +17 -22
  104. package/documentation/introspection.md +82 -0
  105. package/documentation/octets.md +81 -23
  106. package/documentation/protocol.md +13 -3
  107. package/documentation/query.md +29 -4
  108. package/documentation/require.md +15 -0
  109. package/documentation/tree.md +13 -0
  110. package/documentation/vary.md +14 -14
  111. package/features/access.feature +78 -46
  112. package/features/annotation.feature +1 -0
  113. package/features/auth.claim.feature +170 -0
  114. package/features/authorities.basic.feature +141 -0
  115. package/features/authorities.feature +32 -0
  116. package/features/authorities.federation.feature +100 -0
  117. package/features/authorities.tokens.feature +117 -0
  118. package/features/body.feature +2 -0
  119. package/features/cache.feature +109 -5
  120. package/features/cors.feature +6 -1
  121. package/features/debug.feature +34 -0
  122. package/features/directives.feature +3 -0
  123. package/features/dynamic.feature +48 -0
  124. package/features/errors.feature +32 -7
  125. package/features/etag.feature +31 -0
  126. package/features/flow.feature +45 -0
  127. package/features/identity.bans.feature +137 -0
  128. package/features/identity.basic.feature +113 -23
  129. package/features/identity.feature +7 -2
  130. package/features/identity.federation.feature +66 -11
  131. package/features/identity.roles.feature +250 -7
  132. package/features/identity.tokens.feature +54 -4
  133. package/features/introspection.feature +153 -0
  134. package/features/io.feature +38 -1
  135. package/features/methods.feature +47 -0
  136. package/features/octets.download.feature +189 -0
  137. package/features/octets.entries.feature +8 -1
  138. package/features/octets.feature +82 -54
  139. package/features/octets.meta.feature +3 -0
  140. package/features/octets.workflows.feature +239 -19
  141. package/features/probes.feature +14 -0
  142. package/features/{queries.feature → query.feature} +65 -2
  143. package/features/realtime.feature +34 -0
  144. package/features/require.feature +67 -0
  145. package/features/response.feature +38 -3
  146. package/features/routes.feature +93 -2
  147. package/features/steps/Database.ts +16 -9
  148. package/features/steps/Gateway.ts +23 -6
  149. package/features/steps/IdP.ts +30 -25
  150. package/features/steps/Parameters.ts +4 -1
  151. package/features/steps/Realtime.ts +151 -0
  152. package/features/steps/components/echo/manifest.toa.yaml +14 -1
  153. package/features/steps/components/echo/operations/identity.js +7 -0
  154. package/features/steps/components/echo/operations/parameters.js +7 -0
  155. package/features/steps/components/echo.beacon/manifest.toa.yaml +2 -0
  156. package/features/steps/components/echo.beacon/operations/hello.js +5 -0
  157. package/features/steps/components/octets.tester/manifest.toa.yaml +22 -1
  158. package/features/steps/components/octets.tester/operations/authority.js +7 -0
  159. package/features/steps/components/octets.tester/operations/baz.js +1 -2
  160. package/features/steps/components/octets.tester/operations/diversify.js +3 -1
  161. package/features/steps/components/octets.tester/operations/foo.js +2 -2
  162. package/features/steps/components/octets.tester/operations/redirect.js +12 -0
  163. package/features/steps/components/octets.tester/operations/yex.js +16 -0
  164. package/features/steps/components/octets.tester/operations/yield.js +13 -0
  165. package/features/steps/components/pots/manifest.toa.yaml +14 -3
  166. package/features/steps/components/users/manifest.toa.yaml +0 -1
  167. package/features/steps/components/users.properties/manifest.toa.yaml +1 -1
  168. package/features/streams.feature +5 -0
  169. package/features/timing.feature +4 -1
  170. package/features/vary.feature +71 -0
  171. package/package.json +23 -14
  172. package/readme.md +19 -14
  173. package/schemas/annotation.cos.yaml +1 -1
  174. package/schemas/method.cos.yaml +1 -1
  175. package/schemas/node.cos.yaml +2 -0
  176. package/schemas/octets/store.cos.yaml +25 -3
  177. package/schemas/query.cos.yaml +4 -10
  178. package/source/Annotation.ts +3 -3
  179. package/source/Branch.ts +1 -0
  180. package/source/Composition.ts +0 -6
  181. package/source/Context.ts +1 -0
  182. package/source/Directive.ts +4 -5
  183. package/source/Endpoint.ts +55 -15
  184. package/source/Factory.ts +22 -13
  185. package/source/Gateway.ts +67 -19
  186. package/source/HTTP/Context.ts +25 -2
  187. package/source/HTTP/Server.ts +54 -44
  188. package/source/HTTP/exceptions.ts +13 -1
  189. package/source/HTTP/formats/index.ts +3 -3
  190. package/source/HTTP/messages.test.ts +45 -2
  191. package/source/HTTP/messages.ts +23 -5
  192. package/source/Introspection.ts +11 -0
  193. package/source/Mapping.ts +63 -21
  194. package/source/Query.test.ts +3 -3
  195. package/source/Query.ts +117 -33
  196. package/source/RTD/Context.ts +1 -1
  197. package/source/RTD/Endpoint.ts +3 -0
  198. package/source/RTD/Method.ts +16 -0
  199. package/source/RTD/Node.ts +29 -13
  200. package/source/RTD/Route.ts +5 -4
  201. package/source/RTD/Tree.ts +2 -2
  202. package/source/RTD/factory.ts +5 -2
  203. package/source/RTD/syntax/parse.ts +37 -24
  204. package/source/RTD/syntax/types.ts +6 -4
  205. package/source/Remotes.ts +7 -6
  206. package/source/Tenant.ts +6 -20
  207. package/source/deployment.ts +33 -23
  208. package/source/directives/auth/Authorization.ts +37 -14
  209. package/source/directives/auth/Delegate.ts +42 -0
  210. package/source/directives/auth/Federation.ts +84 -0
  211. package/source/directives/auth/Incept.ts +4 -3
  212. package/source/directives/auth/Role.test.ts +53 -6
  213. package/source/directives/auth/Role.ts +22 -14
  214. package/source/directives/auth/split.ts +1 -1
  215. package/source/directives/auth/types.ts +1 -1
  216. package/source/directives/cache/Cache.ts +13 -6
  217. package/source/directives/cache/Control.ts +42 -16
  218. package/source/directives/cors/CORS.ts +1 -1
  219. package/source/directives/dev/Development.ts +1 -1
  220. package/source/directives/flow/Fetch.ts +88 -0
  221. package/source/directives/flow/Flow.ts +34 -0
  222. package/source/directives/flow/index.ts +3 -0
  223. package/source/directives/flow/types.ts +6 -0
  224. package/source/directives/index.ts +3 -1
  225. package/source/directives/io/Input.ts +4 -4
  226. package/source/directives/io/Output.ts +4 -3
  227. package/source/directives/octets/Context.ts +3 -2
  228. package/source/directives/octets/Fetch.ts +11 -10
  229. package/source/directives/octets/List.ts +5 -5
  230. package/source/directives/octets/Octets.ts +1 -3
  231. package/source/directives/octets/Store.ts +30 -10
  232. package/source/directives/octets/bytes.test.ts +30 -0
  233. package/source/directives/octets/bytes.ts +18 -0
  234. package/source/directives/octets/schemas.ts +4 -6
  235. package/source/directives/octets/workflows/Execution.ts +60 -8
  236. package/source/directives/octets/workflows/Workflow.ts +2 -1
  237. package/source/directives/require/Directive.ts +5 -0
  238. package/source/directives/require/Headers.ts +20 -0
  239. package/source/directives/require/Require.ts +28 -0
  240. package/source/directives/require/index.ts +3 -0
  241. package/source/directives/vary/Directive.ts +2 -1
  242. package/source/directives/vary/Embed.ts +14 -8
  243. package/source/directives/vary/Vary.ts +6 -4
  244. package/source/directives/vary/embeddings/Authority.ts +8 -0
  245. package/source/directives/vary/embeddings/Embedding.ts +2 -1
  246. package/source/directives/vary/embeddings/Parameter.ts +14 -0
  247. package/source/directives/vary/embeddings/index.ts +6 -4
  248. package/source/exceptions.ts +17 -11
  249. package/source/manifest.ts +10 -11
  250. package/source/schemas.ts +1 -1
  251. package/transpiled/Annotation.d.ts +3 -3
  252. package/transpiled/Branch.d.ts +1 -0
  253. package/transpiled/Composition.d.ts +0 -1
  254. package/transpiled/Composition.js +0 -4
  255. package/transpiled/Composition.js.map +1 -1
  256. package/transpiled/Context.d.ts +1 -0
  257. package/transpiled/Directive.js +4 -4
  258. package/transpiled/Directive.js.map +1 -1
  259. package/transpiled/Endpoint.d.ts +6 -4
  260. package/transpiled/Endpoint.js +35 -7
  261. package/transpiled/Endpoint.js.map +1 -1
  262. package/transpiled/Factory.d.ts +3 -2
  263. package/transpiled/Factory.js +18 -10
  264. package/transpiled/Factory.js.map +1 -1
  265. package/transpiled/Gateway.d.ts +3 -0
  266. package/transpiled/Gateway.js +51 -12
  267. package/transpiled/Gateway.js.map +1 -1
  268. package/transpiled/HTTP/Context.d.ts +8 -1
  269. package/transpiled/HTTP/Context.js +16 -2
  270. package/transpiled/HTTP/Context.js.map +1 -1
  271. package/transpiled/HTTP/Server.d.ts +13 -2
  272. package/transpiled/HTTP/Server.js +41 -36
  273. package/transpiled/HTTP/Server.js.map +1 -1
  274. package/transpiled/HTTP/exceptions.d.ts +7 -1
  275. package/transpiled/HTTP/exceptions.js +13 -1
  276. package/transpiled/HTTP/exceptions.js.map +1 -1
  277. package/transpiled/HTTP/formats/index.js +3 -3
  278. package/transpiled/HTTP/formats/index.js.map +1 -1
  279. package/transpiled/HTTP/messages.d.ts +1 -0
  280. package/transpiled/HTTP/messages.js +24 -5
  281. package/transpiled/HTTP/messages.js.map +1 -1
  282. package/transpiled/Introspection.d.ts +9 -0
  283. package/transpiled/Introspection.js +3 -0
  284. package/transpiled/Introspection.js.map +1 -0
  285. package/transpiled/Mapping.d.ts +10 -2
  286. package/transpiled/Mapping.js +48 -19
  287. package/transpiled/Mapping.js.map +1 -1
  288. package/transpiled/Query.d.ts +10 -1
  289. package/transpiled/Query.js +83 -30
  290. package/transpiled/Query.js.map +1 -1
  291. package/transpiled/RTD/Context.d.ts +1 -1
  292. package/transpiled/RTD/Endpoint.d.ts +1 -0
  293. package/transpiled/RTD/Method.d.ts +4 -0
  294. package/transpiled/RTD/Method.js +11 -0
  295. package/transpiled/RTD/Method.js.map +1 -1
  296. package/transpiled/RTD/Node.d.ts +4 -1
  297. package/transpiled/RTD/Node.js +23 -12
  298. package/transpiled/RTD/Node.js.map +1 -1
  299. package/transpiled/RTD/Route.d.ts +1 -1
  300. package/transpiled/RTD/Route.js +0 -1
  301. package/transpiled/RTD/Route.js.map +1 -1
  302. package/transpiled/RTD/Tree.d.ts +1 -1
  303. package/transpiled/RTD/Tree.js.map +1 -1
  304. package/transpiled/RTD/factory.js +5 -2
  305. package/transpiled/RTD/factory.js.map +1 -1
  306. package/transpiled/RTD/syntax/parse.js +34 -22
  307. package/transpiled/RTD/syntax/parse.js.map +1 -1
  308. package/transpiled/RTD/syntax/types.d.ts +5 -3
  309. package/transpiled/RTD/syntax/types.js +1 -1
  310. package/transpiled/RTD/syntax/types.js.map +1 -1
  311. package/transpiled/Remotes.d.ts +4 -4
  312. package/transpiled/Remotes.js +6 -5
  313. package/transpiled/Remotes.js.map +1 -1
  314. package/transpiled/Tenant.d.ts +5 -5
  315. package/transpiled/Tenant.js +2 -13
  316. package/transpiled/Tenant.js.map +1 -1
  317. package/transpiled/deployment.d.ts +1 -1
  318. package/transpiled/deployment.js +28 -20
  319. package/transpiled/deployment.js.map +1 -1
  320. package/transpiled/directives/auth/Authorization.js +26 -10
  321. package/transpiled/directives/auth/Authorization.js.map +1 -1
  322. package/transpiled/directives/auth/Delegate.d.ts +10 -0
  323. package/transpiled/directives/auth/Delegate.js +34 -0
  324. package/transpiled/directives/auth/Delegate.js.map +1 -0
  325. package/transpiled/directives/auth/Federation.d.ts +16 -0
  326. package/transpiled/directives/auth/Federation.js +57 -0
  327. package/transpiled/directives/auth/Federation.js.map +1 -0
  328. package/transpiled/directives/auth/Incept.js +4 -3
  329. package/transpiled/directives/auth/Incept.js.map +1 -1
  330. package/transpiled/directives/auth/Role.d.ts +4 -1
  331. package/transpiled/directives/auth/Role.js +20 -14
  332. package/transpiled/directives/auth/Role.js.map +1 -1
  333. package/transpiled/directives/auth/split.js +1 -1
  334. package/transpiled/directives/auth/split.js.map +1 -1
  335. package/transpiled/directives/cache/Cache.d.ts +3 -3
  336. package/transpiled/directives/cache/Cache.js +10 -4
  337. package/transpiled/directives/cache/Cache.js.map +1 -1
  338. package/transpiled/directives/cache/Control.d.ts +2 -1
  339. package/transpiled/directives/cache/Control.js +29 -12
  340. package/transpiled/directives/cache/Control.js.map +1 -1
  341. package/transpiled/directives/cors/CORS.js +1 -1
  342. package/transpiled/directives/cors/CORS.js.map +1 -1
  343. package/transpiled/directives/dev/Development.js +1 -1
  344. package/transpiled/directives/dev/Development.js.map +1 -1
  345. package/transpiled/directives/flow/Fetch.d.ts +13 -0
  346. package/transpiled/directives/flow/Fetch.js +59 -0
  347. package/transpiled/directives/flow/Fetch.js.map +1 -0
  348. package/transpiled/directives/flow/Flow.d.ts +10 -0
  349. package/transpiled/directives/flow/Flow.js +27 -0
  350. package/transpiled/directives/flow/Flow.js.map +1 -0
  351. package/transpiled/directives/flow/index.d.ts +2 -0
  352. package/transpiled/directives/flow/index.js +6 -0
  353. package/transpiled/directives/flow/index.js.map +1 -0
  354. package/transpiled/directives/flow/types.d.ts +5 -0
  355. package/transpiled/directives/flow/types.js.map +1 -0
  356. package/transpiled/directives/index.js +3 -1
  357. package/transpiled/directives/index.js.map +1 -1
  358. package/transpiled/directives/io/Input.js +2 -2
  359. package/transpiled/directives/io/Input.js.map +1 -1
  360. package/transpiled/directives/io/Output.js +2 -2
  361. package/transpiled/directives/io/Output.js.map +1 -1
  362. package/transpiled/directives/octets/Context.js +4 -24
  363. package/transpiled/directives/octets/Context.js.map +1 -1
  364. package/transpiled/directives/octets/Fetch.d.ts +3 -3
  365. package/transpiled/directives/octets/Fetch.js +8 -8
  366. package/transpiled/directives/octets/Fetch.js.map +1 -1
  367. package/transpiled/directives/octets/List.d.ts +3 -3
  368. package/transpiled/directives/octets/List.js +3 -3
  369. package/transpiled/directives/octets/List.js.map +1 -1
  370. package/transpiled/directives/octets/Octets.js +1 -3
  371. package/transpiled/directives/octets/Octets.js.map +1 -1
  372. package/transpiled/directives/octets/Store.d.ts +6 -1
  373. package/transpiled/directives/octets/Store.js +17 -7
  374. package/transpiled/directives/octets/Store.js.map +1 -1
  375. package/transpiled/directives/octets/bytes.d.ts +1 -0
  376. package/transpiled/directives/octets/bytes.js +21 -0
  377. package/transpiled/directives/octets/bytes.js.map +1 -0
  378. package/transpiled/directives/octets/schemas.d.ts +4 -6
  379. package/transpiled/directives/octets/schemas.js +1 -3
  380. package/transpiled/directives/octets/schemas.js.map +1 -1
  381. package/transpiled/directives/octets/workflows/Execution.d.ts +5 -1
  382. package/transpiled/directives/octets/workflows/Execution.js +44 -9
  383. package/transpiled/directives/octets/workflows/Execution.js.map +1 -1
  384. package/transpiled/directives/octets/workflows/Workflow.js +2 -1
  385. package/transpiled/directives/octets/workflows/Workflow.js.map +1 -1
  386. package/transpiled/directives/require/Directive.d.ts +4 -0
  387. package/transpiled/directives/require/Directive.js +3 -0
  388. package/transpiled/directives/require/Directive.js.map +1 -0
  389. package/transpiled/directives/require/Headers.d.ts +7 -0
  390. package/transpiled/directives/require/Headers.js +19 -0
  391. package/transpiled/directives/require/Headers.js.map +1 -0
  392. package/transpiled/directives/require/Require.d.ts +9 -0
  393. package/transpiled/directives/require/Require.js +27 -0
  394. package/transpiled/directives/require/Require.js.map +1 -0
  395. package/transpiled/directives/require/index.d.ts +2 -0
  396. package/transpiled/directives/require/index.js +6 -0
  397. package/transpiled/directives/require/index.js.map +1 -0
  398. package/transpiled/directives/vary/Directive.d.ts +2 -1
  399. package/transpiled/directives/vary/Embed.d.ts +2 -1
  400. package/transpiled/directives/vary/Embed.js +8 -6
  401. package/transpiled/directives/vary/Embed.js.map +1 -1
  402. package/transpiled/directives/vary/Vary.d.ts +2 -2
  403. package/transpiled/directives/vary/Vary.js +3 -3
  404. package/transpiled/directives/vary/Vary.js.map +1 -1
  405. package/transpiled/directives/vary/embeddings/Authority.d.ts +5 -0
  406. package/transpiled/directives/vary/embeddings/Authority.js +10 -0
  407. package/transpiled/directives/vary/embeddings/Authority.js.map +1 -0
  408. package/transpiled/directives/vary/embeddings/Embedding.d.ts +2 -1
  409. package/transpiled/directives/vary/embeddings/Parameter.d.ts +7 -0
  410. package/transpiled/directives/vary/embeddings/Parameter.js +14 -0
  411. package/transpiled/directives/vary/embeddings/Parameter.js.map +1 -0
  412. package/transpiled/directives/vary/embeddings/index.d.ts +2 -2
  413. package/transpiled/directives/vary/embeddings/index.js +8 -4
  414. package/transpiled/directives/vary/embeddings/index.js.map +1 -1
  415. package/transpiled/exceptions.d.ts +3 -2
  416. package/transpiled/exceptions.js +10 -5
  417. package/transpiled/exceptions.js.map +1 -1
  418. package/transpiled/manifest.js +10 -11
  419. package/transpiled/manifest.js.map +1 -1
  420. package/transpiled/schemas.d.ts +1 -1
  421. package/transpiled/schemas.js +2 -2
  422. package/transpiled/schemas.js.map +1 -1
  423. package/transpiled/tsconfig.tsbuildinfo +1 -1
  424. package/tsconfig.json +9 -7
  425. package/components/identity.basic/operations/create.d.ts +0 -10
  426. package/components/identity.basic/operations/create.js +0 -10
  427. package/components/identity.basic/operations/create.js.map +0 -1
  428. package/components/identity.basic/source/create.ts +0 -18
  429. package/components/identity.federation/operations/create.d.ts +0 -10
  430. package/components/identity.federation/operations/create.js.map +0 -1
  431. package/components/identity.federation/operations/schemas.d.ts +0 -59
  432. package/components/identity.federation/operations/schemas.js +0 -9
  433. package/components/identity.federation/operations/schemas.js.map +0 -1
  434. package/components/identity.federation/operations/types.js.map +0 -1
  435. package/components/identity.federation/source/schemas.ts +0 -61
  436. package/components/octets.storage/operations/permute.js +0 -7
  437. package/schemas/octets/context.cos.yaml +0 -1
  438. package/source/HTTP/Server.test.ts +0 -126
  439. package/source/directives/octets/Permute.ts +0 -44
  440. package/transpiled/directives/octets/Permute.d.ts +0 -11
  441. package/transpiled/directives/octets/Permute.js +0 -58
  442. package/transpiled/directives/octets/Permute.js.map +0 -1
  443. /package/{components/identity.federation/operations → transpiled/directives/flow}/types.js +0 -0
@@ -1,34 +1,41 @@
1
- import { type Component } from '@toa.io/core'
2
- import { type Remotes } from './Remotes'
1
+ import { console } from 'openspan'
3
2
  import { Mapping } from './Mapping'
4
- import { type Context } from './Context'
5
3
  import * as http from './HTTP'
4
+ import type { Introspection, Schema } from './Introspection'
5
+ import type { Remote } from '@toa.io/core'
6
+ import type { Remotes } from './Remotes'
7
+ import type { Context } from './Context'
6
8
  import type * as RTD from './RTD'
7
9
 
8
10
  export class Endpoint implements RTD.Endpoint {
9
11
  private readonly endpoint: string
10
12
  private readonly mapping: Mapping
11
- private readonly discovery: Promise<Component>
12
- private remote: Component | null = null
13
+ private readonly discovery: Promise<Remote>
14
+ private remote: Remote | null = null
13
15
 
14
- public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Component>) {
16
+ public constructor (endpoint: string, mapping: Mapping, discovery: Promise<Remote>) {
15
17
  this.endpoint = endpoint
16
18
  this.mapping = mapping
17
19
  this.discovery = discovery
18
20
  }
19
21
 
20
- public async call
21
- (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
22
+ public async call (context: http.Context, parameters: RTD.Parameter[]): Promise<http.OutgoingMessage> {
22
23
  const body = await context.body()
23
24
  const query = this.query(context)
24
25
  const request = this.mapping.fit(body, query, parameters)
25
26
 
26
27
  this.remote ??= await this.discovery
27
28
 
29
+ if (context.debug)
30
+ console.debug('Calling operation', {
31
+ endpoint: this.remote.locator.id + '.' + this.endpoint,
32
+ request
33
+ })
34
+
28
35
  const reply = await this.remote.invoke(this.endpoint, request)
29
36
 
30
37
  if (reply instanceof Error)
31
- throw new http.Conflict(reply)
38
+ throw new http.UnprocessableEntity(reply)
32
39
 
33
40
  const message: http.OutgoingMessage = {}
34
41
 
@@ -42,10 +49,8 @@ export class Endpoint implements RTD.Endpoint {
42
49
  message.headers.set('etag', etag)
43
50
 
44
51
  return message
45
- } else {
52
+ } else
46
53
  message.headers.set('etag', `"${reply._version.toString()}"`)
47
- delete reply._version
48
- }
49
54
  }
50
55
 
51
56
  message.body = reply
@@ -53,6 +58,41 @@ export class Endpoint implements RTD.Endpoint {
53
58
  return message
54
59
  }
55
60
 
61
+ public async explain (parameters: RTD.Parameter[]): Promise<Introspection> {
62
+ this.remote ??= await this.discovery
63
+
64
+ // eslint-disable-next-line @typescript-eslint/await-thenable
65
+ const operation = await this.remote.explain(this.endpoint)
66
+
67
+ let route: Record<string, Schema> | null = null
68
+
69
+ if (operation.input?.type === 'object')
70
+ for (const parameter of parameters) {
71
+ const schema = operation.input.properties[parameter.name]
72
+
73
+ // eslint-disable-next-line max-depth
74
+ if (schema !== undefined) {
75
+ route ??= {}
76
+ route[parameter.name] = schema
77
+
78
+ delete operation.input.properties[parameter.name]
79
+ }
80
+ }
81
+
82
+ const query = this.mapping.explain(operation)
83
+ const introspection: Introspection = {}
84
+
85
+ if (route !== null)
86
+ introspection.route = route
87
+
88
+ if (query !== null)
89
+ introspection.query = query
90
+
91
+ Object.assign(introspection, operation)
92
+
93
+ return introspection
94
+ }
95
+
56
96
  public async close (): Promise<void> {
57
97
  this.remote ??= await this.discovery
58
98
 
@@ -91,13 +131,13 @@ export class EndpointsFactory implements RTD.EndpointsFactory {
91
131
  throw new Error('Cannot create Endpoint without mapping.')
92
132
 
93
133
  const mapping = Mapping.create(method.mapping.query)
94
- const namespace = method.mapping.namespace ?? context.extension?.namespace
95
- const component = method.mapping.component ?? context.extension?.component
134
+ const namespace = method.mapping.namespace ?? context.extension.namespace
135
+ const component = method.mapping.component ?? context.extension.component
96
136
 
97
137
  if (namespace === undefined || component === undefined)
98
138
  throw new Error('Annotation endpoints must be fully qualified.')
99
139
 
100
- const discovery = this.remotes.discover(namespace, component)
140
+ const discovery = this.remotes.discover(namespace, component, context.extension.version)
101
141
 
102
142
  return new Endpoint(method.mapping.endpoint, mapping, discovery)
103
143
  }
package/source/Factory.ts CHANGED
@@ -1,14 +1,19 @@
1
+ import assert from 'node:assert'
2
+ import { decode } from '@toa.io/generic'
1
3
  import { Tenant } from './Tenant'
2
4
  import { Gateway } from './Gateway'
3
5
  import { Remotes } from './Remotes'
4
- import { Tree, syntax } from './RTD'
5
- import { Server } from './HTTP'
6
+ import { Tree } from './RTD'
6
7
  import { EndpointsFactory } from './Endpoint'
7
8
  import { families, interceptors } from './directives'
8
9
  import { DirectivesFactory } from './Directive'
9
10
  import { Composition } from './Composition'
10
11
  import * as root from './root'
11
12
  import { Interception } from './Interception'
13
+ import * as http from './HTTP'
14
+ import type { Manifest } from '@toa.io/norm'
15
+ import type { Branch } from './Branch'
16
+ import type { syntax } from './RTD'
12
17
  import type { Broadcast } from './Gateway'
13
18
  import type { Connector, Locator, extensions } from '@toa.io/core'
14
19
 
@@ -19,23 +24,27 @@ export class Factory implements extensions.Factory {
19
24
  this.boot = boot
20
25
  }
21
26
 
22
- public tenant (locator: Locator, node: syntax.Node): Connector {
27
+ public tenant (locator: Locator, node: syntax.Node, manifest: Manifest): Connector {
23
28
  const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL, locator.id)
24
29
 
25
- return new Tenant(broadcast, locator, node)
30
+ const branch: Branch = {
31
+ namespace: locator.namespace,
32
+ component: locator.name,
33
+ isolated: locator.namespace === 'identity',
34
+ node,
35
+ version: manifest.version
36
+ }
37
+
38
+ return new Tenant(broadcast, branch)
26
39
  }
27
40
 
28
41
  public service (): Connector | null {
29
- const debug = process.env.TOA_EXPOSITION_DEBUG === '1'
30
- const trace = process.env.TOA_EXPOSITION_TRACE === '1'
31
- const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
32
-
33
- const server = Server.create({
34
- methods: syntax.verbs,
35
- debug,
36
- trace
37
- })
42
+ assert.ok(process.env.TOA_EXPOSITION_PROPERTIES,
43
+ 'TOA_EXPOSITION_PROPERTIES is undefined')
38
44
 
45
+ const options = decode<http.Options>(process.env.TOA_EXPOSITION_PROPERTIES)
46
+ const broadcast: Broadcast = this.boot.bindings.broadcast(CHANNEL)
47
+ const server = http.Server.create({ ...options })
39
48
  const remotes = new Remotes(this.boot)
40
49
  const node = root.resolve()
41
50
  const methods = new EndpointsFactory(remotes)
package/source/Gateway.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import assert from 'node:assert'
2
+ import { console } from 'openspan'
1
3
  import { type bindings, Connector } from '@toa.io/core'
2
4
  import * as http from './HTTP'
3
5
  import { rethrow } from './exceptions'
4
6
  import type { Interception } from './Interception'
5
- import type { Method, Parameter, Tree } from './RTD'
7
+ import type { Node, Method, Parameter, Tree, Match } from './RTD'
6
8
  import type { Label } from './discovery'
7
9
  import type { Branch } from './Branch'
8
10
 
@@ -10,6 +12,7 @@ export class Gateway extends Connector {
10
12
  private readonly broadcast: Broadcast
11
13
  private readonly tree: Tree
12
14
  private readonly interceptor: Interception
15
+ private readonly merged = new Set<string>()
13
16
 
14
17
  public constructor (broadcast: Broadcast, tree: Tree, interception: Interception) {
15
18
  super()
@@ -28,15 +31,10 @@ export class Gateway extends Connector {
28
31
  if (interception !== null)
29
32
  return interception
30
33
 
31
- const match = this.tree.match(context.url.pathname)
32
-
33
- if (match === null)
34
- throw new http.NotFound()
34
+ const { node, parameters } = this.match(context)
35
35
 
36
- const {
37
- node,
38
- parameters
39
- } = match
36
+ if (context.request.method === 'OPTIONS')
37
+ return await this.explain(node, parameters)
40
38
 
41
39
  if (!(context.request.method in node.methods))
42
40
  throw new http.MethodNotAllowed()
@@ -44,12 +42,13 @@ export class Gateway extends Connector {
44
42
  const method = node.methods[context.request.method]
45
43
 
46
44
  const interruption = await context.timing.capture('preflight',
47
- method.directives.preflight(context, parameters))
45
+ method.directives.preflight(context, parameters)).catch(rethrow)
48
46
 
49
47
  const response = interruption ??
50
48
  await context.timing.capture('call', this.call(method, context, parameters))
51
49
 
52
- await context.timing.capture('settle', method.directives.settle(context, response))
50
+ await context.timing.capture('settle',
51
+ method.directives.settle(context, response)).catch(rethrow)
53
52
 
54
53
  return response
55
54
  }
@@ -57,17 +56,41 @@ export class Gateway extends Connector {
57
56
  protected override async open (): Promise<void> {
58
57
  await this.discover()
59
58
 
60
- console.info('Gateway has started and is awaiting resource branches.')
59
+ console.info('Gateway started')
61
60
  }
62
61
 
63
62
  protected override dispose (): void {
64
- console.info('Gateway is closed.')
63
+ console.info('Gateway is closed')
65
64
  }
66
65
 
67
- private async call (method: Method, context: http.Context, parameters: Parameter[]):
68
- Promise<http.OutgoingMessage> {
66
+ private match (context: http.Context): Match {
67
+ const match = this.tree.match(context.url.pathname)
68
+
69
+ if (match === null)
70
+ throw new http.NotFound('Route not found')
71
+
72
+ if (match.node.forward === null)
73
+ return match
74
+
75
+ const destination = match.node.forward.replace(/\/:([^/]+)/g,
76
+ (_, name) => {
77
+ const value = match.parameters.find((parameter) => parameter.name === name)?.value
78
+
79
+ assert.ok(value !== undefined, `Forwarded parameter '${name}' not found`)
80
+
81
+ return `/${value}`
82
+ })
83
+
84
+ const forward = this.tree.match(destination)
85
+
86
+ assert.ok(forward !== null, 'Forwarded route not found')
87
+
88
+ return forward
89
+ }
90
+
91
+ private async call (method: Method, context: http.Context, parameters: Parameter[]): Promise<http.OutgoingMessage> {
69
92
  if (context.url.pathname[context.url.pathname.length - 1] !== '/')
70
- throw new http.NotFound('Trailing slash is required.')
93
+ throw new http.NotFound('Trailing slash is required')
71
94
 
72
95
  if (context.encoder === null)
73
96
  throw new http.NotAcceptable()
@@ -80,19 +103,44 @@ export class Gateway extends Connector {
80
103
  .catch(rethrow) as http.OutgoingMessage
81
104
  }
82
105
 
106
+ private async explain (node: Node, parameters: Parameter[]): Promise<http.OutgoingMessage> {
107
+ const body = await node.explain(parameters)
108
+ const allow = [...Object.keys(node.methods)].join(', ')
109
+ const headers = new Headers({ allow })
110
+
111
+ return { body, headers }
112
+ }
113
+
83
114
  private async discover (): Promise<void> {
84
115
  await this.broadcast.receive<Branch>('expose', this.merge.bind(this))
85
116
  await this.broadcast.transmit<null>('ping', null)
86
117
  }
87
118
 
88
119
  private merge (branch: Branch): void {
120
+ const id = branch.namespace + '.' + branch.component + '@' + branch.version
121
+
122
+ if (this.merged.has(id)) {
123
+ console.debug('Branch already merged, ignoring', {
124
+ namespace: branch.namespace,
125
+ component: branch.component,
126
+ version: branch.version
127
+ })
128
+
129
+ return
130
+ }
131
+
132
+ this.merged.add(id)
133
+
89
134
  try {
90
135
  this.tree.merge(branch.node, branch)
91
136
 
92
- console.info('Resource branch of ' +
93
- `'${branch.namespace}.${branch.component}' has been merged.`)
137
+ console.info('Branch merged', {
138
+ namespace: branch.namespace,
139
+ component: branch.component,
140
+ version: branch.version
141
+ })
94
142
  } catch (exception) {
95
- console.error(exception)
143
+ console.error('Branch merge exception', exception as Error)
96
144
  }
97
145
  }
98
146
  }
@@ -1,4 +1,5 @@
1
1
  import Negotiator from 'negotiator'
2
+ import { console } from 'openspan'
2
3
  import { Timing } from './Timing'
3
4
  import { type Format, formats, types } from './formats'
4
5
  import { read } from './messages'
@@ -6,22 +7,29 @@ import type { OutgoingMessage } from './messages'
6
7
  import type * as http from 'node:http'
7
8
 
8
9
  export class Context {
10
+ public readonly authority: string
9
11
  public readonly request: IncomingMessage
10
12
  public readonly url: URL
11
13
  public readonly subtype: string | null = null
12
14
  public readonly encoder: Format | null = null
13
15
  public readonly timing: Timing
16
+ public readonly debug: boolean
14
17
 
15
18
  public readonly pipelines: Pipelines = {
16
19
  body: [],
17
20
  response: []
18
21
  }
19
22
 
20
- public constructor (request: IncomingMessage, trace = false) {
23
+ public constructor (authority: string, request: IncomingMessage, properties: Properties) {
24
+ this.authority = authority
21
25
  this.request = request
22
26
 
23
27
  this.url = new URL(request.url, `https://${request.headers.host}`)
24
- this.timing = new Timing(trace)
28
+ this.timing = new Timing(properties.trace)
29
+ this.debug = properties.debug
30
+
31
+ if (this.debug)
32
+ this.log(request)
25
33
 
26
34
  if (this.request.headers.accept !== undefined) {
27
35
  const match = SUBTYPE.exec(this.request.headers.accept)
@@ -52,6 +60,16 @@ export class Context {
52
60
  ? value
53
61
  : this.pipelines.body.reduce((value, transform) => transform(value), value)
54
62
  }
63
+
64
+ private log (request: IncomingMessage): void {
65
+ const headers = { ...request.headers }
66
+
67
+ if (headers.authorization !== undefined)
68
+ // only scheme
69
+ headers.authorization = headers.authorization.slice(0, headers.authorization.indexOf(' '))
70
+
71
+ console.debug('Received request', { method: request.method, url: request.url, headers })
72
+ }
55
73
  }
56
74
 
57
75
  export interface IncomingMessage extends http.IncomingMessage {
@@ -64,4 +82,9 @@ interface Pipelines {
64
82
  response: Array<(output: OutgoingMessage) => void>
65
83
  }
66
84
 
85
+ interface Properties {
86
+ debug: boolean
87
+ trace: boolean
88
+ }
89
+
67
90
  const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/
@@ -1,10 +1,10 @@
1
1
  import fs from 'node:fs'
2
2
  import os from 'node:os'
3
3
  import * as http from 'node:http'
4
- import assert from 'node:assert'
5
4
  import { once } from 'node:events'
5
+ import { setTimeout } from 'node:timers/promises'
6
+ import { console } from 'openspan'
6
7
  import { Connector } from '@toa.io/core'
7
- import { promex } from '@toa.io/generic'
8
8
  import { type OutgoingMessage, write } from './messages'
9
9
  import { ClientError, Exception } from './exceptions'
10
10
  import { Context } from './Context'
@@ -13,32 +13,22 @@ import type { IncomingMessage } from './Context'
13
13
  export class Server extends Connector {
14
14
  private readonly server: http.Server = http.createServer()
15
15
  private readonly properties: Properties
16
+ private readonly authorities: Record<string, string>
16
17
  private process?: Processing
18
+ private ready: boolean = false
19
+ private startedAt: number = 0
17
20
 
18
21
  private constructor (properties: Properties) {
19
22
  super()
20
23
 
21
24
  this.properties = properties
25
+ this.authorities = Object.fromEntries(Object.entries(properties.authorities).map(([key, value]) => [value, key]))
22
26
 
23
27
  this.server.on('request', (req, res) => this.listener(req, res))
24
28
  }
25
29
 
26
- public get port (): number {
27
- if (this.properties.port !== 0)
28
- return this.properties.port
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
36
- }
37
-
38
- public static create (options?: Partial<Properties>): Server {
39
- const properties = options === undefined
40
- ? DEFAULTS
41
- : { ...DEFAULTS, ...options }
30
+ public static create (options: Options): Server {
31
+ const properties: Properties = Object.assign({}, DEFAULTS, options)
42
32
 
43
33
  return new Server(properties)
44
34
  }
@@ -48,21 +38,29 @@ export class Server extends Connector {
48
38
  }
49
39
 
50
40
  protected override async open (): Promise<void> {
41
+ this.startedAt = Date.now()
51
42
  this.server.listen(this.properties.port)
52
43
 
53
44
  await once(this.server, 'listening')
54
45
 
55
- console.info('HTTP Server is listening.')
46
+ console.info('HTTP Server is listening')
47
+
48
+ await setTimeout(this.properties.delay)
49
+
50
+ this.ready = true
51
+
52
+ console.info('Ready')
56
53
  }
57
54
 
58
55
  protected override async close (): Promise<void> {
59
56
  this.server.close()
57
+ this.ready = false
60
58
 
61
- console.info('HTTP Server stopped accepting new connections.')
59
+ console.info('Stopped accepting new connections')
62
60
 
63
61
  await once(this.server, 'close')
64
62
 
65
- console.info('HTTP Server has been stopped.')
63
+ console.info('Stopped')
66
64
  }
67
65
 
68
66
  private listener (request: http.IncomingMessage, response: http.ServerResponse): void {
@@ -72,18 +70,23 @@ export class Server extends Connector {
72
70
  return
73
71
  }
74
72
 
75
- if (request.url === undefined) {
76
- response.writeHead(400).end()
73
+ if (request.url === '/.ready') {
74
+ if (this.ready)
75
+ response.writeHead(200, { 'cache-control': 'no-store' }).end()
76
+ else {
77
+ const remaining = (Math.ceil((Date.now() - this.startedAt) / 1000)).toString()
78
+
79
+ response.writeHead(503, { 'retry-after': remaining }).end()
80
+ }
77
81
 
78
82
  return
79
83
  }
80
84
 
81
- assert.ok(this.process !== undefined,
82
- 'No processing function has been attached to the server.')
83
-
84
- const context = new Context(request as IncomingMessage, this.properties.trace)
85
+ const host = request.headers.host!
86
+ const authority = this.authorities[host] ?? host
87
+ const context = new Context(authority, request as IncomingMessage, this.properties)
85
88
 
86
- this.process(context)
89
+ this.process!(context)
87
90
  .then(this.success(context, response))
88
91
  .catch(this.fail(context, response))
89
92
  }
@@ -112,17 +115,17 @@ export class Server extends Connector {
112
115
  if (!context.request.complete)
113
116
  await adam(context.request)
114
117
 
115
- response.statusCode = exception instanceof Exception
116
- ? exception.status
117
- : 500
118
+ response.statusCode = exception instanceof Exception ? exception.status : 500
118
119
 
119
120
  const message: OutgoingMessage = { status: response.statusCode }
120
- const verbose = exception instanceof ClientError || this.properties.debug
121
121
 
122
- if (verbose)
123
- message.body = exception instanceof Exception
124
- ? exception.body
125
- : (exception.stack ?? exception.message)
122
+ if (context.encoder === null)
123
+ message.body = undefined
124
+ else if (exception instanceof ClientError || this.properties.debug)
125
+ message.body =
126
+ exception instanceof Exception
127
+ ? exception.body
128
+ : exception.stack ?? exception.message
126
129
 
127
130
  write(context, response, message)
128
131
  }
@@ -131,28 +134,35 @@ export class Server extends Connector {
131
134
 
132
135
  // https://github.com/whatwg/fetch/issues/1254
133
136
  async function adam (request: http.IncomingMessage): Promise<void> {
134
- const completed = promex()
135
137
  const devnull = fs.createWriteStream(os.devNull)
136
138
 
137
- request
138
- .on('end', completed.callback)
139
- .pipe(devnull)
139
+ request.pipe(devnull)
140
140
 
141
- return completed
141
+ await once(request, 'end')
142
142
  }
143
143
 
144
- const DEFAULTS: Properties = {
145
- methods: new Set<string>(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']),
144
+ export const PORT = 8000
145
+ export const DELAY = 3 // seconds
146
+
147
+ const DEFAULTS: Omit<Properties, 'authorities'> = {
148
+ methods: new Set<string>(['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'LOCK', 'UNLOCK']),
146
149
  debug: false,
147
150
  trace: false,
148
- port: 8000
151
+ port: PORT,
152
+ delay: DELAY * 1000
149
153
  }
150
154
 
151
155
  interface Properties {
156
+ authorities: Record<string, string>
152
157
  methods: Set<string>
153
158
  debug: boolean
154
159
  trace: boolean
155
160
  port: number
161
+ delay: number
162
+ }
163
+
164
+ export type Options = { authorities: Properties['authorities'] } & {
165
+ [K in Exclude<keyof Properties, 'authorities'>]?: Properties[K]
156
166
  }
157
167
 
158
168
  export type Processing = (input: Context) => Promise<OutgoingMessage>
@@ -37,11 +37,17 @@ export class NotFound extends ClientError {
37
37
  }
38
38
 
39
39
  export class Conflict extends ClientError {
40
- public constructor (body: any) {
40
+ public constructor (body?: any) {
41
41
  super(409, body)
42
42
  }
43
43
  }
44
44
 
45
+ export class UnprocessableEntity extends ClientError {
46
+ public constructor (body?: any) {
47
+ super(422, body)
48
+ }
49
+ }
50
+
45
51
  export class MethodNotAllowed extends ClientError {
46
52
  public constructor () {
47
53
  super(405)
@@ -65,3 +71,9 @@ export class PreconditionFailed extends ClientError {
65
71
  super(412)
66
72
  }
67
73
  }
74
+
75
+ export class RequestEntityTooLarge extends ClientError {
76
+ public constructor (body?: any) {
77
+ super(413, body)
78
+ }
79
+ }
@@ -5,10 +5,10 @@ import * as msgpack from './msgpack'
5
5
  import * as text from './text'
6
6
 
7
7
  export const formats: Record<string, Format> = {
8
- [msgpack.type]: msgpack,
9
- [yaml.type]: yaml,
10
8
  [json.type]: json,
11
- [text.type]: text
9
+ [yaml.type]: yaml,
10
+ [text.type]: text,
11
+ [msgpack.type]: msgpack
12
12
  }
13
13
 
14
14
  export const types = Object.keys(formats)
@@ -1,9 +1,13 @@
1
- import { Readable } from 'node:stream'
1
+ import { PassThrough, Readable } from 'node:stream'
2
+ import * as streamConsumers from 'node:stream/consumers'
3
+ import { once } from 'node:events'
2
4
  import { generate } from 'randomstring'
3
5
  import * as msgpack from 'msgpackr'
4
- import { read } from './messages'
6
+ import { multipart, read, type OutgoingMessage } from './messages'
5
7
  import { BadRequest, UnsupportedMediaType } from './exceptions'
8
+ import { formats } from './formats'
6
9
  import { Timing } from './Timing'
10
+ import type * as http from 'node:http'
7
11
  import type { Context } from './Context'
8
12
 
9
13
  beforeEach(() => {
@@ -69,6 +73,45 @@ describe('read', () => {
69
73
 
70
74
  await expect(read(request)).rejects.toThrow(BadRequest)
71
75
  })
76
+
77
+ it('should output correct mulitpart format', async () => {
78
+ const response = new class extends PassThrough {
79
+ public readonly headers = new Headers()
80
+
81
+ public setHeader (key: string, value: string): this {
82
+ this.headers.set(key, value)
83
+
84
+ return this
85
+ }
86
+ }()
87
+
88
+ const context = { encoder: formats['text/plain'] } as unknown as Context
89
+ const message = { body: Readable.from(['Hello', 'New', 'World']) } as unknown as OutgoingMessage
90
+
91
+ multipart(message, context, response as unknown as http.ServerResponse)
92
+
93
+ await once(message.body, 'end')
94
+
95
+ const result = await streamConsumers.text(response)
96
+
97
+ expect(result).toBe([
98
+ '--cut',
99
+ '',
100
+ 'ACK',
101
+ '--cut',
102
+ '',
103
+ 'Hello',
104
+ '--cut',
105
+ '',
106
+ 'New',
107
+ '--cut',
108
+ '',
109
+ 'World',
110
+ '--cut',
111
+ '',
112
+ 'FIN',
113
+ '--cut--'].join('\r\n'))
114
+ })
72
115
  })
73
116
 
74
117
  export function createContext