@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,3 +1,4 @@
1
+ import assert from 'node:assert'
1
2
  import { match } from 'matchacho'
2
3
  import * as http from '../../HTTP'
3
4
  import { Anonymous } from './Anonymous'
@@ -9,9 +10,10 @@ import { Echo } from './Echo'
9
10
  import { split } from './split'
10
11
  import { Scheme } from './Scheme'
11
12
  import { PRIMARY, PROVIDERS } from './schemes'
13
+ import type { Output } from '../../io'
12
14
  import type { Component } from '@toa.io/core'
13
15
  import type { Remotes } from '../../Remotes'
14
- import type { Family, Output } from '../../Directive'
16
+ import type { Family } from '../../Directive'
15
17
  import type { Parameter } from '../../RTD'
16
18
  import type {
17
19
  AuthenticationResult,
@@ -25,7 +27,8 @@ import type {
25
27
  Schemes
26
28
  } from './types'
27
29
 
28
- class Authorization implements Family<Directive, Extension> {
30
+ export class Authorization implements Family<Directive, Extension> {
31
+ public readonly depends: string[] = ['Vary']
29
32
  public readonly name: string = 'auth'
30
33
  public readonly mandatory: boolean = true
31
34
 
@@ -35,23 +38,24 @@ class Authorization implements Family<Directive, Extension> {
35
38
  private bans: Component | null = null
36
39
 
37
40
  public create (name: string, value: any, remotes: Remotes): Directive {
38
- const Class = CLASSES[name]
41
+ assert.ok(name in CLASSES,
42
+ `Directive '${name}' is not provided by the '${this.name}' family.`)
39
43
 
40
- if (Class === undefined)
41
- throw new Error(`Directive '${name}' is not provided by the '${this.name}' family.`)
44
+ const Class = CLASSES[name]
42
45
 
43
46
  for (const name of REMOTES)
44
47
  this.discovery[name] ??= remotes.discover('identity', name)
45
48
 
46
49
  return match(Class,
47
- Role, () => new Role(value, this.discovery.roles),
48
- Rule, () => new Rule(value, this.create.bind(this)),
49
- Incept, () => new Incept(value, this.discovery),
50
+ Role, () => new Role(value as string | string[], this.discovery.roles),
51
+ Rule, () => new Rule(value as Record<string, string>, this.create.bind(this)),
52
+ Incept, () => new Incept(value as string, this.discovery),
50
53
  () => new Class(value))
51
54
  }
52
55
 
53
- public async preflight
54
- (directives: Directive[], input: Input, parameters: Parameter[]): Promise<Output> {
56
+ public async preflight (directives: Directive[],
57
+ input: Input,
58
+ parameters: Parameter[]): Promise<Output> {
55
59
  const identity = await this.resolve(input.headers.authorization)
56
60
 
57
61
  input.identity = identity
@@ -67,37 +71,32 @@ class Authorization implements Family<Directive, Extension> {
67
71
  else throw new http.Forbidden()
68
72
  }
69
73
 
70
- public async settle
71
- (directives: Directive[], request: Input, response: http.OutgoingMessage): Promise<void> {
72
- for (const directive of directives)
73
- await directive.settle?.(request, response)
74
+ public async settle (directives: Directive[],
75
+ request: Input,
76
+ response: http.OutgoingMessage): Promise<void> {
77
+ for (const directive of directives) await directive.settle?.(request, response)
74
78
 
75
79
  const identity = request.identity
76
80
 
77
- if (identity === null)
78
- return
81
+ if (identity === null) return
79
82
 
80
- if (identity.scheme === PRIMARY && !identity.refresh)
81
- return
83
+ if (identity.scheme === PRIMARY && !identity.refresh) return
82
84
 
83
85
  // Role directive may have already set the value
84
- if (identity.roles === undefined)
85
- await Role.set(identity, this.discovery.roles)
86
+ if (identity.roles === undefined) await Role.set(identity, this.discovery.roles)
86
87
 
87
88
  this.tokens ??= await this.discovery.tokens
88
89
 
89
90
  const token = await this.tokens.invoke<string>('encrypt', { input: { identity } })
90
91
  const authorization = `Token ${token}`
91
92
 
92
- if (response.headers === undefined)
93
- response.headers = new Headers()
93
+ if (response.headers === undefined) response.headers = new Headers()
94
94
 
95
95
  response.headers.set('authorization', authorization)
96
96
  }
97
97
 
98
98
  private async resolve (authorization: string | undefined): Promise<Identity | null> {
99
- if (authorization === undefined)
100
- return null
99
+ if (authorization === undefined) return null
101
100
 
102
101
  const [scheme, credentials] = split(authorization)
103
102
  const provider = PROVIDERS[scheme]
@@ -107,16 +106,15 @@ class Authorization implements Family<Directive, Extension> {
107
106
 
108
107
  this.schemes[scheme] ??= await this.discovery[provider]
109
108
 
110
- const result = await this.schemes[scheme]
111
- .invoke<AuthenticationResult>('authenticate', { input: credentials })
109
+ const result = await this.schemes[scheme].invoke<AuthenticationResult>('authenticate', {
110
+ input: credentials
111
+ })
112
112
 
113
- if (result instanceof Error)
114
- return null
113
+ if (result instanceof Error) return null
115
114
 
116
115
  const identity = result.identity
117
116
 
118
- if (scheme !== PRIMARY && await this.banned(identity))
119
- throw new http.Unauthorized()
117
+ if (scheme !== PRIMARY && (await this.banned(identity))) throw new http.Unauthorized()
120
118
 
121
119
  identity.scheme = scheme
122
120
  identity.refresh = result.refresh
@@ -143,6 +141,4 @@ const CLASSES: Record<string, new (value: any, argument?: any) => Directive> = {
143
141
  echo: Echo
144
142
  }
145
143
 
146
- const REMOTES: Remote[] = ['basic', 'tokens', 'roles', 'bans']
147
-
148
- export = new Authorization()
144
+ const REMOTES: Remote[] = ['basic', 'federation', 'tokens', 'roles', 'bans']
@@ -25,7 +25,7 @@ export class Incept implements Directive {
25
25
  throw new http.Conflict('Identity inception has failed as the response body ' +
26
26
  ` does not contain the '${this.property}' property.`)
27
27
 
28
- const [scheme, credentials] = split(request.headers.authorization as string)
28
+ const [scheme, credentials] = split(request.headers.authorization!)
29
29
  const provider = PROVIDERS[scheme]
30
30
 
31
31
  this.schemes[scheme] ??= await this.discovery[provider]
@@ -1,5 +1,5 @@
1
1
  import { type Parameter } from '../../RTD'
2
- import { type Directive, type Identity } from './types'
2
+ import type { Input, Directive, Identity } from './types'
3
3
 
4
4
  export class Rule implements Directive {
5
5
  private readonly directives: Directive[] = []
@@ -13,7 +13,7 @@ export class Rule implements Directive {
13
13
  }
14
14
 
15
15
  public async authorize
16
- (identity: Identity | null, input: any, parameters: Parameter[]): Promise<boolean> {
16
+ (identity: Identity | null, input: Input, parameters: Parameter[]): Promise<boolean> {
17
17
  for (const directive of this.directives) {
18
18
  const authorized = await directive.authorize(identity, input, parameters)
19
19
 
@@ -1,3 +1,3 @@
1
- import Family from './Family'
1
+ import { Authorization } from './Authorization'
2
2
 
3
- export = Family
3
+ export const authorization = new Authorization()
@@ -2,7 +2,8 @@ import { type Remote, type Scheme } from './types'
2
2
 
3
3
  export const PROVIDERS: Record<Scheme, Remote> = {
4
4
  basic: 'basic',
5
- token: 'tokens'
5
+ token: 'tokens',
6
+ bearer: 'federation'
6
7
  }
7
8
 
8
9
  export const PRIMARY: Scheme = 'token'
@@ -2,11 +2,14 @@ import { type Component } from '@toa.io/core'
2
2
  import { type Maybe } from '@toa.io/types'
3
3
  import { type Parameter } from '../../RTD'
4
4
  import type * as http from '../../HTTP'
5
- import type * as directive from '../../Directive'
5
+ import type * as io from '../../io'
6
6
 
7
7
  export interface Directive {
8
- authorize: (identity: Identity | null, input: Input, parameters: Parameter[]) =>
9
- boolean | Promise<boolean>
8
+ authorize: (
9
+ identity: Identity | null,
10
+ input: Input,
11
+ parameters: Parameter[],
12
+ ) => boolean | Promise<boolean>
10
13
 
11
14
  reply?: (identity: Identity | null) => http.OutgoingMessage
12
15
 
@@ -28,10 +31,10 @@ export interface Ban {
28
31
  banned: boolean
29
32
  }
30
33
 
31
- export type Input = directive.Input & Extension
34
+ export type Input = io.Input & Extension
32
35
  export type AuthenticationResult = Maybe<{ identity: Identity, refresh: boolean }>
33
36
 
34
- export type Scheme = 'basic' | 'token'
35
- export type Remote = 'basic' | 'tokens' | 'roles' | 'bans'
37
+ export type Scheme = 'basic' | 'token' | 'bearer'
38
+ export type Remote = 'basic' | 'federation' | 'tokens' | 'roles' | 'bans'
36
39
  export type Discovery = Record<Remote, Promise<Component>>
37
40
  export type Schemes = Record<Scheme, Component>
@@ -1,10 +1,11 @@
1
- import { type Input, type Output, type Family } from '../../Directive'
2
1
  import { Control } from './Control'
3
- import { type Directive } from './types'
4
2
  import { Exact } from './Exact'
3
+ import type { Input, Output } from '../../io'
4
+ import type { Directive } from './types'
5
+ import type { Family } from '../../Directive'
5
6
  import type * as http from '../../HTTP'
6
7
 
7
- class Cache implements Family<Directive> {
8
+ export class Cache implements Family<Directive> {
8
9
  public readonly name: string = 'cache'
9
10
  public readonly mandatory: boolean = false
10
11
 
@@ -32,5 +33,3 @@ const constructors: Record<string, new (value: any) => Directive> = {
32
33
  control: Control,
33
34
  exact: Exact
34
35
  }
35
-
36
- export = new Cache()
@@ -1,3 +1,3 @@
1
- import Family from './Family'
1
+ import { Cache } from './Cache'
2
2
 
3
- export = Family
3
+ export const cache = new Cache()
@@ -1,4 +1,4 @@
1
- import { type Input } from '../../Directive'
1
+ import type { Input } from '../../io'
2
2
 
3
3
  export interface Directive {
4
4
  set: (input: Input, headers: Headers) => void
@@ -0,0 +1,54 @@
1
+ import type { Input, Output } from '../../io'
2
+ import type { Interceptor } from '../../Interception'
3
+
4
+ export class CORS implements Interceptor {
5
+ public readonly name = 'cors'
6
+ public readonly mandatory = true
7
+
8
+ private readonly allowedHeaders = new Set<string>(['accept', 'authorization', 'content-type'])
9
+
10
+ private readonly headers = new Headers({
11
+ 'access-control-allow-methods': 'GET, POST, PUT, PATCH, DELETE',
12
+ 'access-control-allow-credentials': 'true',
13
+ 'access-control-allow-headers': Array.from(this.allowedHeaders).join(', '),
14
+ 'access-control-max-age': '3600',
15
+ 'cache-control': 'public, max-age=3600',
16
+ vary: 'origin'
17
+ })
18
+
19
+ public intercept (input: Input): Output {
20
+ const origin = input.headers.origin
21
+
22
+ if (origin === undefined)
23
+ return null
24
+
25
+ if (input.method === 'OPTIONS')
26
+ return this.preflightResponse(origin)
27
+
28
+ input.pipelines.response.push((output) => {
29
+ output.headers ??= new Headers()
30
+ output.headers.set('access-control-allow-origin', origin)
31
+ output.headers.set('access-control-expose-headers',
32
+ 'authorization, content-type, content-length, etag')
33
+
34
+ if (input.method === 'GET' || input.method === 'HEAD' || input.method === 'OPTIONS')
35
+ output.headers.append('vary', 'origin')
36
+ })
37
+
38
+ return null
39
+ }
40
+
41
+ public allowHeader (header: string): void {
42
+ this.allowedHeaders.add(header.toLowerCase())
43
+ this.headers.set('access-control-allow-headers', Array.from(this.allowedHeaders).join(', '))
44
+ }
45
+
46
+ private preflightResponse (origin: string): Output {
47
+ this.headers.set('access-control-allow-origin', origin)
48
+
49
+ return {
50
+ status: 204,
51
+ headers: this.headers
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,3 @@
1
+ import { CORS } from './CORS'
2
+
3
+ export const cors = new CORS()
@@ -1,9 +1,10 @@
1
- import { type Input, type Output, type Family } from '../../Directive'
2
1
  import { Stub } from './Stub'
3
2
  import { Throw } from './Throw'
4
3
  import { type Directive } from './types'
4
+ import type { Input, Output } from '../../io'
5
+ import type { Family } from '../../Directive'
5
6
 
6
- class Development implements Family<Directive> {
7
+ export class Development implements Family<Directive> {
7
8
  public readonly name: string = 'dev'
8
9
  public readonly mandatory: boolean = false
9
10
 
@@ -32,5 +33,3 @@ const constructors: Record<string, new (value: any) => Directive> = {
32
33
  stub: Stub,
33
34
  throw: Throw
34
35
  }
35
-
36
- export = new Development()
@@ -1,10 +1,10 @@
1
- import { type Output } from '../../Directive'
2
- import { type Directive } from './types'
1
+ import type { Output } from '../../io'
2
+ import type { Directive } from './types'
3
3
 
4
4
  export class Stub implements Directive {
5
- private readonly value: any
5
+ private readonly value: unknown
6
6
 
7
- public constructor (value: any) {
7
+ public constructor (value: unknown) {
8
8
  this.value = value
9
9
  }
10
10
 
@@ -1,10 +1,10 @@
1
- import { type Output } from '../../Directive'
2
- import { type Directive } from './types'
1
+ import type { Output } from '../../io'
2
+ import type { Directive } from './types'
3
3
 
4
4
  export class Throw implements Directive {
5
- private readonly message: any
5
+ private readonly message: string
6
6
 
7
- public constructor (message: any) {
7
+ public constructor (message: string) {
8
8
  this.message = message
9
9
  }
10
10
 
@@ -1,3 +1,3 @@
1
- import Family from './Family'
1
+ import { Development } from './Development'
2
2
 
3
- export = Family
3
+ export const dev = new Development()
@@ -1,4 +1,4 @@
1
- import { type Input, type Output } from '../../Directive'
1
+ import type { Input, Output } from '../../io'
2
2
 
3
3
  export interface Directive {
4
4
  apply: (input: Input) => Output
@@ -1,7 +1,11 @@
1
- import { type Family } from '../Directive'
2
- import Dev from './dev'
3
- import Auth from './auth'
4
- import Cache from './cache'
5
- import Octets from './octets'
1
+ import { dev } from './dev'
2
+ import { authorization } from './auth'
3
+ import { cache } from './cache'
4
+ import { octets } from './octets'
5
+ import { cors } from './cors'
6
+ import { vary } from './vary'
7
+ import type { Family } from '../Directive'
8
+ import type { Interceptor } from '../Interception'
6
9
 
7
- export const families: Family[] = [Auth, Octets, Dev, Cache]
10
+ export const families: Family[] = [authorization, cache, octets, vary, dev]
11
+ export const interceptors: Interceptor[] = [cors]
@@ -1,5 +1,5 @@
1
1
  import * as schemas from './schemas'
2
- import type { Output } from '../../Directive'
2
+ import type { Output } from '../../io'
3
3
  import type { Directive } from './types'
4
4
 
5
5
  export class Context implements Directive {
@@ -1,32 +1,73 @@
1
+ import { Readable } from 'stream'
1
2
  import { NotFound } from '../../HTTP'
2
3
  import * as schemas from './schemas'
4
+ import { Workflow } from './workflows'
5
+ import type { Parameter } from '../../RTD'
6
+ import type { Unit } from './workflows'
3
7
  import type { Maybe } from '@toa.io/types'
4
8
  import type { Component } from '@toa.io/core'
5
- import type { Output } from '../../Directive'
6
-
9
+ import type { Output } from '../../io'
7
10
  import type { Directive, Input } from './types'
11
+ import type { Remotes } from '../../Remotes'
12
+ import type { Entry } from '@toa.io/extensions.storages'
8
13
 
9
14
  export class Delete implements Directive {
10
15
  public readonly targeted = true
11
16
 
17
+ private readonly workflow?: Workflow
12
18
  private readonly discovery: Promise<Component>
13
19
  private storage: Component | null = null
14
20
 
15
- public constructor (value: null, discovery: Promise<Component>) {
16
- schemas.remove.validate(value)
21
+ public constructor (options: Options | null, discovery: Promise<Component>, remotes: Remotes) {
22
+ schemas.remove.validate(options)
23
+
24
+ if (options?.workflow !== undefined)
25
+ this.workflow = new Workflow(options.workflow, remotes)
17
26
 
18
27
  this.discovery = discovery
19
28
  }
20
29
 
21
- public async apply (storage: string, request: Input): Promise<Output> {
30
+ public async apply (storage: string, request: Input, parameters: Parameter[]): Promise<Output> {
22
31
  this.storage ??= await this.discovery
23
32
 
24
- const input = { storage, path: request.path }
25
- const error = await this.storage.invoke<Maybe<unknown>>('delete', { input })
33
+ const entry = await this.storage.invoke<Maybe<Entry>>('get',
34
+ { input: { storage, path: request.url } })
26
35
 
27
- if (error instanceof Error)
36
+ if (entry instanceof Error)
28
37
  throw new NotFound()
29
38
 
30
- return {}
39
+ const output: Output = {}
40
+
41
+ if (this.workflow !== undefined) {
42
+ output.status = 202
43
+ output.body = Readable.from(this.execute(request, storage, entry, parameters))
44
+ } else
45
+ await this.delete(storage, request)
46
+
47
+ return output
48
+ }
49
+
50
+ private async delete (storage: string, request: Input): Promise<void> {
51
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
52
+ await this.storage!.invoke('delete',
53
+ { input: { storage, path: request.url } })
31
54
  }
55
+
56
+ // eslint-disable-next-line max-params
57
+ private async * execute
58
+ (request: Input, storage: string, entry: Entry, parameters: Parameter[]): AsyncGenerator {
59
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
60
+ for await (const chunk of this.workflow!.execute(request, storage, entry, parameters)) {
61
+ yield chunk
62
+
63
+ if (typeof chunk === 'object' && chunk !== null && 'error' in chunk)
64
+ return
65
+ }
66
+
67
+ await this.delete(storage, request)
68
+ }
69
+ }
70
+
71
+ export interface Options {
72
+ workflow?: Unit[] | Unit
32
73
  }
@@ -5,18 +5,18 @@ import type { Maybe } from '@toa.io/types'
5
5
  import type { Entry } from '@toa.io/extensions.storages'
6
6
  import type { Readable } from 'node:stream'
7
7
  import type { Component } from '@toa.io/core'
8
- import type { Output } from '../../Directive'
8
+ import type { Output } from '../../io'
9
9
 
10
10
  import type { Directive, Input } from './types'
11
11
 
12
12
  export class Fetch implements Directive {
13
13
  public readonly targeted = true
14
14
 
15
- private readonly permissions: Permissions = { blob: true, meta: false }
15
+ private readonly permissions: Required<Permissions> = { blob: true, meta: false }
16
16
  private readonly discovery: Promise<Component>
17
17
  private storage: Component = null as unknown as Component
18
18
 
19
- public constructor (permissions: Partial<Permissions> | null, discovery: Promise<Component>) {
19
+ public constructor (permissions: Permissions | null, discovery: Promise<Component>) {
20
20
  schemas.fetch.validate(permissions)
21
21
 
22
22
  Object.assign(this.permissions, permissions)
@@ -26,19 +26,22 @@ export class Fetch implements Directive {
26
26
  public async apply (storage: string, request: Input): Promise<Output> {
27
27
  this.storage ??= await this.discovery
28
28
 
29
- if (request.url.slice(-5) === ':meta')
30
- return await this.get(storage, request)
31
- else
32
- return await this.fetch(storage, request)
33
- }
29
+ const variant = posix.basename(request.url).includes('.')
30
+ const metadata = request.subtype === 'octets.entry'
34
31
 
35
- private async fetch (storage: string, request: Input): Promise<Output> {
36
- const filename = posix.basename(request.url)
37
- const variant = filename.includes('.')
32
+ if (!variant && metadata)
33
+ if (this.permissions.meta)
34
+ return this.get(storage, request)
35
+ else
36
+ throw new Forbidden('Metadata is not accessible.')
38
37
 
39
38
  if (!variant && !this.permissions.blob)
40
39
  throw new Forbidden('BLOB variant must be specified.')
41
40
 
41
+ return await this.fetch(storage, request)
42
+ }
43
+
44
+ private async fetch (storage: string, request: Input): Promise<Output> {
42
45
  if ('if-none-match' in request.headers)
43
46
  return { status: 304 }
44
47
 
@@ -58,11 +61,7 @@ export class Fetch implements Directive {
58
61
  }
59
62
 
60
63
  private async get (storage: string, request: Input): Promise<Output> {
61
- if (!this.permissions.meta)
62
- throw new Forbidden('Metadata is not accessible.')
63
-
64
- const path = request.url.slice(0, -5)
65
- const input = { storage, path }
64
+ const input = { storage, path: request.url }
66
65
  const entry = await this.storage.invoke<Maybe<Entry>>('get', { input })
67
66
 
68
67
  if (entry instanceof Error)
@@ -72,9 +71,9 @@ export class Fetch implements Directive {
72
71
  }
73
72
  }
74
73
 
75
- interface Permissions {
76
- blob: boolean
77
- meta: boolean
74
+ export interface Permissions {
75
+ blob?: boolean
76
+ meta?: boolean
78
77
  }
79
78
 
80
79
  interface FetchResult {
@@ -1,32 +1,62 @@
1
- import { NotFound } from '../../HTTP'
1
+ import { posix } from 'node:path'
2
+ import { Forbidden, NotFound } from '../../HTTP'
2
3
  import * as schemas from './schemas'
4
+ import type { Entry } from '@toa.io/extensions.storages'
3
5
  import type { Maybe } from '@toa.io/types'
4
6
  import type { Component } from '@toa.io/core'
5
- import type { Output } from '../../Directive'
7
+ import type { Output } from '../../io'
6
8
 
7
9
  import type { Directive, Input } from './types'
8
10
 
9
11
  export class List implements Directive {
10
12
  public readonly targeted = false
11
13
 
14
+ private readonly permissions: Required<Permissions> = { meta: false }
12
15
  private readonly discovery: Promise<Component>
13
16
  private storage: Component | null = null
14
17
 
15
- public constructor (value: null, discovery: Promise<Component>) {
16
- schemas.remove.validate(value)
18
+ public constructor (permissions: Permissions | null, discovery: Promise<Component>) {
19
+ schemas.list.validate(permissions)
17
20
 
21
+ Object.assign(this.permissions, permissions)
18
22
  this.discovery = discovery
19
23
  }
20
24
 
21
25
  public async apply (storage: string, request: Input): Promise<Output> {
22
26
  this.storage ??= await this.discovery
23
27
 
24
- const input = { storage, path: request.path }
25
- const list = await this.storage.invoke<Maybe<unknown>>('list', { input })
28
+ const metadata = request.subtype === 'octets.entries'
29
+
30
+ if (metadata && !this.permissions.meta)
31
+ throw new Forbidden('Metadata is not accessible.')
32
+
33
+ const input = { storage, path: request.url }
34
+ const list = await this.storage.invoke<Maybe<string[]>>('list', { input })
26
35
 
27
36
  if (list instanceof Error)
28
37
  throw new NotFound()
29
38
 
30
- return { body: list }
39
+ const body = metadata
40
+ ? await this.expand(storage, request.url, list)
41
+ : list
42
+
43
+ return { body }
31
44
  }
45
+
46
+ private async expand (storage: string, prefix: string, list: string[]):
47
+ Promise<Array<Maybe<Entry>>> {
48
+ const promises = list.map(async (id) => {
49
+ const path = posix.join(prefix, id)
50
+ const input = { storage, path }
51
+
52
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- ensured in `apply`
53
+ return this.storage!.invoke<Maybe<Entry>>('get', { input })
54
+ })
55
+
56
+ return await Promise.all(promises)
57
+ }
58
+ }
59
+
60
+ export interface Permissions {
61
+ meta?: boolean
32
62
  }