acrylblends 0.3.0 → 0.4.0

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 (315) hide show
  1. package/dist/index.d.ts +6 -1
  2. package/dist/index.js +28 -3
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/acryl-inspect/plugin.json +2 -1
  6. package/plugins/acryl-inspect/src/report.ts +16 -13
  7. package/plugins/acryl-inspect/src/service.ts +9 -7
  8. package/plugins/acryl-inspect/tests/report.spec.ts +7 -8
  9. package/plugins/acryl-inspect/tests/service.spec.ts +11 -10
  10. package/plugins/acryl-inspect/upstream.json +2 -2
  11. package/plugins/acryl-node-server/LICENSE +26 -0
  12. package/plugins/acryl-node-server/plugin.json +2 -1
  13. package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
  14. package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
  15. package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
  16. package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
  17. package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
  18. package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
  19. package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
  20. package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
  21. package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
  22. package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
  23. package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
  24. package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
  25. package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
  26. package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
  27. package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
  28. package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
  29. package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
  30. package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
  31. package/plugins/acryl-node-server/src/index.ts +19 -6
  32. package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
  33. package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
  34. package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
  35. package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
  36. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
  37. package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
  38. package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
  39. package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
  40. package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
  41. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
  42. package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
  43. package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
  44. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
  45. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
  46. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
  47. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
  48. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
  49. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
  50. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
  51. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
  52. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
  53. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
  54. package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
  55. package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
  56. package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
  57. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
  58. package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
  59. package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
  60. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
  61. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
  62. package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
  63. package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
  64. package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
  65. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
  66. package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
  67. package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
  68. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
  69. package/plugins/acryl-node-server/tests/server.spec.ts +44 -8
  70. package/plugins/acryl-node-server/upstream.json +3 -3
  71. package/plugins/acryl-router/LICENSE +26 -0
  72. package/plugins/acryl-router/plugin.json +2 -1
  73. package/plugins/acryl-router/src/client.ts +2 -0
  74. package/plugins/acryl-router/src/connection.ts +42 -0
  75. package/plugins/acryl-router/src/core/app-base.ts +544 -0
  76. package/plugins/acryl-router/src/core/app.test.ts +3833 -0
  77. package/plugins/acryl-router/src/core/app.ts +34 -0
  78. package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
  79. package/plugins/acryl-router/src/core/client/client.ts +249 -0
  80. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
  81. package/plugins/acryl-router/src/core/client/index.ts +17 -0
  82. package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
  83. package/plugins/acryl-router/src/core/client/types.ts +393 -0
  84. package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
  85. package/plugins/acryl-router/src/core/client/utils.ts +117 -0
  86. package/plugins/acryl-router/src/core/compose.test.ts +751 -0
  87. package/plugins/acryl-router/src/core/compose.ts +73 -0
  88. package/plugins/acryl-router/src/core/context.test.ts +629 -0
  89. package/plugins/acryl-router/src/core/context.ts +781 -0
  90. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
  91. package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
  92. package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
  93. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
  94. package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
  95. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
  96. package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
  97. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
  98. package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
  99. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
  100. package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
  101. package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
  102. package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
  103. package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
  104. package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
  105. package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
  106. package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
  107. package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
  108. package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
  109. package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
  110. package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
  111. package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
  112. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
  113. package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
  114. package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
  115. package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
  116. package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
  117. package/plugins/acryl-router/src/core/http-exception.ts +77 -0
  118. package/plugins/acryl-router/src/core/index.ts +53 -0
  119. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
  120. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
  121. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
  122. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
  123. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
  124. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
  125. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
  126. package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
  127. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
  128. package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
  129. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
  130. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
  131. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
  132. package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
  133. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
  134. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
  135. package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
  136. package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
  137. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
  138. package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
  139. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
  140. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
  141. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
  142. package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
  143. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
  144. package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
  145. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
  146. package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
  147. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
  148. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
  149. package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
  150. package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
  151. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
  152. package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
  153. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
  154. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
  155. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
  156. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
  157. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
  158. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
  159. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
  160. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
  161. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
  162. package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
  163. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
  164. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
  165. package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
  166. package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
  167. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
  168. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
  169. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
  170. package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
  171. package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
  172. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
  173. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
  174. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
  175. package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
  176. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
  177. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
  178. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
  179. package/plugins/acryl-router/src/core/request/constants.ts +1 -0
  180. package/plugins/acryl-router/src/core/request.test.ts +751 -0
  181. package/plugins/acryl-router/src/core/request.ts +502 -0
  182. package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
  183. package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
  184. package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
  185. package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
  186. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
  187. package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
  188. package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
  189. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
  190. package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
  191. package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
  192. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
  193. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
  194. package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
  195. package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
  196. package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
  197. package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
  198. package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
  199. package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
  200. package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
  201. package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
  202. package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
  203. package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
  204. package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
  205. package/plugins/acryl-router/src/core/router/utils.ts +1 -0
  206. package/plugins/acryl-router/src/core/router.ts +103 -0
  207. package/plugins/acryl-router/src/core/types.test.ts +4134 -0
  208. package/plugins/acryl-router/src/core/types.ts +2782 -0
  209. package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
  210. package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
  211. package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
  212. package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
  213. package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
  214. package/plugins/acryl-router/src/core/utils/body.ts +263 -0
  215. package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
  216. package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
  217. package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
  218. package/plugins/acryl-router/src/core/utils/color.ts +56 -0
  219. package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
  220. package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
  221. package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
  222. package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
  223. package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
  224. package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
  225. package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
  226. package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
  227. package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
  228. package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
  229. package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
  230. package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
  231. package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
  232. package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
  233. package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
  234. package/plugins/acryl-router/src/core/utils/html.ts +182 -0
  235. package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
  236. package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
  237. package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
  238. package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
  239. package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
  240. package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
  241. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
  242. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
  243. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
  244. package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
  245. package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
  246. package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
  247. package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
  248. package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
  249. package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
  250. package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
  251. package/plugins/acryl-router/src/core/utils/types.ts +123 -0
  252. package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
  253. package/plugins/acryl-router/src/core/utils/url.ts +337 -0
  254. package/plugins/acryl-router/src/core/validator/index.ts +8 -0
  255. package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
  256. package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
  257. package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
  258. package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
  259. package/plugins/acryl-router/src/helpers/index.ts +13 -3
  260. package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
  261. package/plugins/acryl-router/src/index.ts +6 -6
  262. package/plugins/acryl-router/src/middleware/index.ts +25 -6
  263. package/plugins/acryl-router/src/middleware/loopback-only.ts +19 -13
  264. package/plugins/acryl-router/src/service.ts +256 -64
  265. package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
  266. package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
  267. package/plugins/acryl-router/tests/loader.spec.ts +3 -2
  268. package/plugins/acryl-router/tests/service.spec.ts +264 -66
  269. package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
  270. package/plugins/acryl-router/upstream.json +2 -2
  271. package/plugins/acryl-router-http/plugin.json +2 -1
  272. package/plugins/acryl-router-http/src/bridge.ts +3 -1
  273. package/plugins/acryl-router-http/tests/adapter.spec.ts +16 -12
  274. package/plugins/acryl-router-http/tests/surfaces.spec.ts +12 -10
  275. package/plugins/acryl-router-http/upstream.json +3 -3
  276. package/plugins/acryl-state/NOTICE +30 -0
  277. package/plugins/acryl-state/plugin.json +1 -1
  278. package/plugins/acryl-state/src/cell.ts +1 -1
  279. package/plugins/acryl-state/src/service.ts +33 -15
  280. package/plugins/acryl-state/upstream.json +6 -4
  281. package/plugins/builder/script.ts +4 -7
  282. package/plugins/extensions/index.ts +2 -2
  283. package/plugins/extensions/resolve.ts +28 -3
  284. package/plugins/openai/prompt.ts +9 -7
  285. package/plugins/tsconfig.json +5 -4
  286. package/templates/agent/src/routes.ts +37 -27
  287. package/templates/agent/test/model.test.ts +2 -1
  288. package/templates/agent/tsconfig.json +8 -5
  289. package/templates/blank/src/routes.ts +6 -4
  290. package/templates/blank/tsconfig.json +2 -4
  291. package/templates/todo/src/page.ts +1 -1
  292. package/templates/todo/src/todo.ts +56 -29
  293. package/templates/todo/tsconfig.json +2 -4
  294. package/templates/todo/upstream.json +2 -2
  295. package/plugins/acryl-router/src/compose.ts +0 -21
  296. package/plugins/acryl-router/src/context.ts +0 -59
  297. package/plugins/acryl-router/src/helpers/read-body.ts +0 -59
  298. package/plugins/acryl-router/src/helpers/sse.ts +0 -83
  299. package/plugins/acryl-router/src/helpers/validate.ts +0 -44
  300. package/plugins/acryl-router/src/http-error.ts +0 -21
  301. package/plugins/acryl-router/src/middleware/body-limit.ts +0 -25
  302. package/plugins/acryl-router/src/middleware/cors.ts +0 -46
  303. package/plugins/acryl-router/src/middleware/logger.ts +0 -21
  304. package/plugins/acryl-router/src/middleware/request-id.ts +0 -24
  305. package/plugins/acryl-router/src/middleware/secure-headers.ts +0 -23
  306. package/plugins/acryl-router/src/pattern.ts +0 -89
  307. package/plugins/acryl-router/src/registrar.ts +0 -90
  308. package/plugins/acryl-router/src/table.ts +0 -156
  309. package/plugins/acryl-router/src/types.ts +0 -73
  310. package/plugins/acryl-router/src/util.ts +0 -23
  311. package/plugins/acryl-router/tests/api.spec.ts +0 -223
  312. package/plugins/acryl-router/tests/conformance.ts +0 -170
  313. package/plugins/acryl-router/tests/helpers.spec.ts +0 -172
  314. package/plugins/acryl-router/tests/middleware.spec.ts +0 -183
  315. package/plugins/acryl-router/tests/table.spec.ts +0 -47
@@ -0,0 +1,434 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { basicAuth } from './index.ts'
3
+ import { App } from '../../app.ts'
4
+
5
+ describe('Basic Auth by Middleware', () => {
6
+ let handlerExecuted: boolean
7
+
8
+ beforeEach(() => {
9
+ handlerExecuted = false
10
+ })
11
+
12
+ const app = new App()
13
+
14
+ const username = 'acryl-user-a'
15
+ const password = 'acryl-password-a'
16
+ const unicodePassword = '炎'
17
+
18
+ const usernameB = 'acryl-user-b'
19
+ const passwordB = 'acryl-password-b'
20
+
21
+ const usernameC = 'acryl-user-c'
22
+ const passwordC = 'acryl-password-c'
23
+
24
+ app.use(
25
+ '/auth/*',
26
+ basicAuth({
27
+ username,
28
+ password,
29
+ })
30
+ )
31
+ // Test multiple handlers
32
+ app.use('/auth/*', async (c, next) => {
33
+ c.header('x-custom', 'foo')
34
+ await next()
35
+ })
36
+
37
+ app.use(
38
+ '/auth-unicode/*',
39
+ basicAuth({
40
+ username: username,
41
+ password: unicodePassword,
42
+ })
43
+ )
44
+
45
+ app.use(
46
+ '/auth-multi/*',
47
+ basicAuth(
48
+ {
49
+ username: usernameB,
50
+ password: passwordB,
51
+ },
52
+ {
53
+ username: usernameC,
54
+ password: passwordC,
55
+ }
56
+ )
57
+ )
58
+
59
+ app.use(
60
+ '/auth-override-func/*',
61
+ basicAuth({
62
+ username: username,
63
+ password: password,
64
+ hashFunction: (data: string) => createHash('sha256').update(data).digest('hex'),
65
+ })
66
+ )
67
+
68
+ app.use('/nested/*', async (c, next) => {
69
+ const auth = basicAuth({ username: username, password: password })
70
+ return auth(c, next)
71
+ })
72
+
73
+ app.use('/verify-user/*', async (c, next) => {
74
+ const auth = basicAuth({
75
+ verifyUser: (username, password, c) => {
76
+ return (
77
+ c.req.path === '/verify-user' &&
78
+ username === 'dynamic-user' &&
79
+ password === 'acryl-password'
80
+ )
81
+ },
82
+ })
83
+ return auth(c, next)
84
+ })
85
+
86
+ app.use(
87
+ '/auth-custom-invalid-user-message-string/*',
88
+ basicAuth({
89
+ username,
90
+ password,
91
+ invalidUserMessage: 'Custom unauthorized message as string',
92
+ })
93
+ )
94
+
95
+ app.use(
96
+ '/auth-custom-invalid-user-message-object/*',
97
+ basicAuth({
98
+ username,
99
+ password,
100
+ invalidUserMessage: { message: 'Custom unauthorized message as object' },
101
+ })
102
+ )
103
+
104
+ app.use(
105
+ '/auth-custom-invalid-user-message-function-string/*',
106
+ basicAuth({
107
+ username,
108
+ password,
109
+ invalidUserMessage: () => 'Custom unauthorized message as function string',
110
+ })
111
+ )
112
+
113
+ app.use(
114
+ '/auth-custom-invalid-user-message-function-object/*',
115
+ basicAuth({
116
+ username,
117
+ password,
118
+ invalidUserMessage: () => ({ message: 'Custom unauthorized message as function object' }),
119
+ })
120
+ )
121
+
122
+ app.get('/auth/*', (c) => {
123
+ handlerExecuted = true
124
+ return c.text('auth')
125
+ })
126
+ app.get('/auth-unicode/*', (c) => {
127
+ handlerExecuted = true
128
+ return c.text('auth')
129
+ })
130
+ app.get('/auth-multi/*', (c) => {
131
+ handlerExecuted = true
132
+ return c.text('auth')
133
+ })
134
+ app.get('/auth-override-func/*', (c) => {
135
+ handlerExecuted = true
136
+ return c.text('auth')
137
+ })
138
+
139
+ app.get('/nested/*', (c) => {
140
+ handlerExecuted = true
141
+ return c.text('nested')
142
+ })
143
+
144
+ app.get('/verify-user', (c) => {
145
+ handlerExecuted = true
146
+ return c.text('verify-user')
147
+ })
148
+
149
+ app.get('/auth-custom-invalid-user-message-string/*', (c) => {
150
+ handlerExecuted = true
151
+ return c.text('auth')
152
+ })
153
+ app.get('/auth-custom-invalid-user-message-object/*', (c) => {
154
+ handlerExecuted = true
155
+ return c.text('auth')
156
+ })
157
+ app.get('/auth-custom-invalid-user-message-function-string/*', (c) => {
158
+ handlerExecuted = true
159
+ return c.text('auth')
160
+ })
161
+
162
+ app.get('/auth-custom-invalid-user-message-function-object/*', (c) => {
163
+ handlerExecuted = true
164
+ return c.text('auth')
165
+ })
166
+
167
+ it('Should not authorize', async () => {
168
+ const req = new Request('http://localhost/auth/a')
169
+ const res = await app.request(req)
170
+ expect(res).not.toBeNull()
171
+ expect(res.status).toBe(401)
172
+ expect(handlerExecuted).toBeFalsy()
173
+ expect(await res.text()).toBe('Unauthorized')
174
+ expect(res.headers.get('x-custom')).toBeNull()
175
+ })
176
+
177
+ it('Should authorize', async () => {
178
+ const credential = Buffer.from(username + ':' + password).toString('base64')
179
+
180
+ const req = new Request('http://localhost/auth/a')
181
+ req.headers.set('Authorization', `Basic ${credential}`)
182
+ const res = await app.request(req)
183
+ expect(res).not.toBeNull()
184
+ expect(handlerExecuted).toBeTruthy()
185
+ expect(res.status).toBe(200)
186
+ expect(await res.text()).toBe('auth')
187
+ expect(res.headers.get('x-custom')).toBe('foo')
188
+ })
189
+
190
+ it('Should authorize Unicode', async () => {
191
+ const credential = Buffer.from(username + ':' + unicodePassword).toString('base64')
192
+
193
+ const req = new Request('http://localhost/auth-unicode/a')
194
+ req.headers.set('Authorization', `Basic ${credential}`)
195
+ const res = await app.request(req)
196
+ expect(handlerExecuted).toBeTruthy()
197
+ expect(res).not.toBeNull()
198
+ expect(res.status).toBe(200)
199
+ expect(await res.text()).toBe('auth')
200
+ })
201
+
202
+ it('Should authorize multiple users', async () => {
203
+ let credential = Buffer.from(usernameB + ':' + passwordB).toString('base64')
204
+
205
+ let req = new Request('http://localhost/auth-multi/b')
206
+ req.headers.set('Authorization', `Basic ${credential}`)
207
+ let res = await app.request(req)
208
+ expect(handlerExecuted).toBeTruthy()
209
+ expect(res).not.toBeNull()
210
+ expect(res.status).toBe(200)
211
+ expect(await res.text()).toBe('auth')
212
+
213
+ handlerExecuted = false
214
+ credential = Buffer.from(usernameC + ':' + passwordC).toString('base64')
215
+ req = new Request('http://localhost/auth-multi/c')
216
+ req.headers.set('Authorization', `Basic ${credential}`)
217
+ res = await app.request(req)
218
+ expect(handlerExecuted).toBeTruthy()
219
+ expect(res).not.toBeNull()
220
+ expect(res.status).toBe(200)
221
+ expect(await res.text()).toBe('auth')
222
+ })
223
+
224
+ it('Should authorize with sha256 function override', async () => {
225
+ const credential = Buffer.from(username + ':' + password).toString('base64')
226
+
227
+ const req = new Request('http://localhost/auth-override-func/a')
228
+ req.headers.set('Authorization', `Basic ${credential}`)
229
+ const res = await app.request(req)
230
+ expect(handlerExecuted).toBeTruthy()
231
+ expect(res).not.toBeNull()
232
+ expect(res.status).toBe(200)
233
+ expect(await res.text()).toBe('auth')
234
+ })
235
+
236
+ it('Should authorize - nested', async () => {
237
+ const credential = Buffer.from(username + ':' + password).toString('base64')
238
+
239
+ const req = new Request('http://localhost/nested')
240
+ req.headers.set('Authorization', `Basic ${credential}`)
241
+ const res = await app.request(req)
242
+ expect(handlerExecuted).toBeTruthy()
243
+ expect(res).not.toBeNull()
244
+ expect(res.status).toBe(200)
245
+ expect(await res.text()).toBe('nested')
246
+ })
247
+
248
+ it('Should not authorize - nested', async () => {
249
+ const credential = Buffer.from('foo' + ':' + 'bar').toString('base64')
250
+
251
+ const req = new Request('http://localhost/nested')
252
+ req.headers.set('Authorization', `Basic ${credential}`)
253
+ const res = await app.request(req)
254
+ expect(handlerExecuted).toBeFalsy()
255
+ expect(res).not.toBeNull()
256
+ expect(res.status).toBe(401)
257
+ expect(await res.text()).toBe('Unauthorized')
258
+ })
259
+
260
+ it('Should authorize - verifyUser', async () => {
261
+ const credential = Buffer.from('dynamic-user' + ':' + 'acryl-password').toString('base64')
262
+
263
+ const req = new Request('http://localhost/verify-user')
264
+ req.headers.set('Authorization', `Basic ${credential}`)
265
+ const res = await app.request(req)
266
+ expect(handlerExecuted).toBeTruthy()
267
+ expect(res).not.toBeNull()
268
+ expect(res.status).toBe(200)
269
+ expect(await res.text()).toBe('verify-user')
270
+ })
271
+
272
+ it('Should not authorize - verifyUser', async () => {
273
+ const credential = Buffer.from('foo' + ':' + 'bar').toString('base64')
274
+
275
+ const req = new Request('http://localhost/verify-user')
276
+ req.headers.set('Authorization', `Basic ${credential}`)
277
+ const res = await app.request(req)
278
+ expect(handlerExecuted).toBeFalsy()
279
+ expect(res).not.toBeNull()
280
+ expect(res.status).toBe(401)
281
+ expect(await res.text()).toBe('Unauthorized')
282
+ })
283
+
284
+ it('Should not authorize - custom invalid user message as string', async () => {
285
+ const req = new Request('http://localhost/auth-custom-invalid-user-message-string')
286
+ const res = await app.request(req)
287
+ expect(res).not.toBeNull()
288
+ expect(res.status).toBe(401)
289
+ expect(handlerExecuted).toBeFalsy()
290
+ expect(await res.text()).toBe('Custom unauthorized message as string')
291
+ })
292
+
293
+ it('Should not authorize - custom invalid user message as object', async () => {
294
+ const req = new Request('http://localhost/auth-custom-invalid-user-message-object')
295
+ const res = await app.request(req)
296
+ expect(res).not.toBeNull()
297
+ expect(res.status).toBe(401)
298
+ expect(res.headers.get('Content-Type')).toMatch('application/json')
299
+ expect(handlerExecuted).toBeFalsy()
300
+ expect(await res.text()).toBe('{"message":"Custom unauthorized message as object"}')
301
+ })
302
+
303
+ it('Should not authorize - custom invalid user message as function string', async () => {
304
+ const req = new Request('http://localhost/auth-custom-invalid-user-message-function-string')
305
+ const res = await app.request(req)
306
+ expect(res).not.toBeNull()
307
+ expect(res.status).toBe(401)
308
+ expect(handlerExecuted).toBeFalsy()
309
+ expect(await res.text()).toBe('Custom unauthorized message as function string')
310
+ })
311
+
312
+ it('Should not authorize - custom invalid user message as function object', async () => {
313
+ const req = new Request('http://localhost/auth-custom-invalid-user-message-function-object')
314
+ const res = await app.request(req)
315
+ expect(res).not.toBeNull()
316
+ expect(res.status).toBe(401)
317
+ expect(res.headers.get('Content-Type')).toMatch('application/json')
318
+ expect(handlerExecuted).toBeFalsy()
319
+ expect(await res.text()).toBe('{"message":"Custom unauthorized message as function object"}')
320
+ })
321
+ })
322
+
323
+ describe('Basic Auth with onAuthSuccess', () => {
324
+ const username = 'callback-user'
325
+ const password = 'callback-pass'
326
+
327
+ it('should call onAuthSuccess callback on successful auth', async () => {
328
+ type Env = { Variables: { custom: string } }
329
+ const app = new App<Env>()
330
+ let callbackCalled = false
331
+ let callbackUsername = ''
332
+
333
+ app.use(
334
+ '/*',
335
+ basicAuth({
336
+ username,
337
+ password,
338
+ onAuthSuccess: (c, u) => {
339
+ callbackCalled = true
340
+ callbackUsername = u
341
+ c.set('custom', 'value')
342
+ },
343
+ })
344
+ )
345
+ app.get('/', (c) => c.text(c.get('custom') || 'no-custom'))
346
+
347
+ const credential = Buffer.from(`${username}:${password}`).toString('base64')
348
+ const res = await app.request('/', {
349
+ headers: { Authorization: `Basic ${credential}` },
350
+ })
351
+
352
+ expect(callbackCalled).toBe(true)
353
+ expect(callbackUsername).toBe(username)
354
+ expect(res.status).toBe(200)
355
+ expect(await res.text()).toBe('value')
356
+ })
357
+
358
+ it('should support async onAuthSuccess callback', async () => {
359
+ type Env = { Variables: { asyncValue: string } }
360
+ const app = new App<Env>()
361
+
362
+ app.use(
363
+ '/*',
364
+ basicAuth({
365
+ username,
366
+ password,
367
+ onAuthSuccess: async (c) => {
368
+ await new Promise((resolve) => setTimeout(resolve, 10))
369
+ c.set('asyncValue', 'done')
370
+ },
371
+ })
372
+ )
373
+ app.get('/', (c) => c.text(c.get('asyncValue') || 'not-done'))
374
+
375
+ const credential = Buffer.from(`${username}:${password}`).toString('base64')
376
+ const res = await app.request('/', {
377
+ headers: { Authorization: `Basic ${credential}` },
378
+ })
379
+ expect(res.status).toBe(200)
380
+ expect(await res.text()).toBe('done')
381
+ })
382
+
383
+ it('should not call onAuthSuccess on failed auth', async () => {
384
+ const app = new App()
385
+ let callbackCalled = false
386
+
387
+ app.use(
388
+ '/*',
389
+ basicAuth({
390
+ username,
391
+ password,
392
+ onAuthSuccess: () => {
393
+ callbackCalled = true
394
+ },
395
+ })
396
+ )
397
+ app.get('/', (c) => c.text('ok'))
398
+
399
+ const credential = Buffer.from('wrong:wrong').toString('base64')
400
+ const res = await app.request('/', {
401
+ headers: { Authorization: `Basic ${credential}` },
402
+ })
403
+
404
+ expect(callbackCalled).toBe(false)
405
+ expect(res.status).toBe(401)
406
+ })
407
+
408
+ it('should work with verifyUser mode', async () => {
409
+ type Env = { Variables: { verified: string } }
410
+ const app = new App<Env>()
411
+ let callbackUsername = ''
412
+
413
+ app.use(
414
+ '/*',
415
+ basicAuth({
416
+ verifyUser: (u, p) => u === username && p === password,
417
+ onAuthSuccess: (c, u) => {
418
+ callbackUsername = u
419
+ c.set('verified', 'yes')
420
+ },
421
+ })
422
+ )
423
+ app.get('/', (c) => c.text(c.get('verified') || 'no'))
424
+
425
+ const credential = Buffer.from(`${username}:${password}`).toString('base64')
426
+ const res = await app.request('/', {
427
+ headers: { Authorization: `Basic ${credential}` },
428
+ })
429
+
430
+ expect(callbackUsername).toBe(username)
431
+ expect(res.status).toBe(200)
432
+ expect(await res.text()).toBe('yes')
433
+ })
434
+ })
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @module
3
+ * Basic Auth Middleware for App.
4
+ */
5
+
6
+ import type { Context } from '../../context.ts'
7
+ import { HTTPException } from '../../http-exception.ts'
8
+ import type { MiddlewareHandler } from '../../types.ts'
9
+ import { auth } from '../../utils/basic-auth.ts'
10
+ import { timingSafeEqual } from '../../utils/buffer.ts'
11
+
12
+ type MessageFunction = (c: Context) => string | object | Promise<string | object>
13
+
14
+ type BasicAuthOptions =
15
+ | {
16
+ username: string
17
+ password: string
18
+ realm?: string
19
+ hashFunction?: Function
20
+ invalidUserMessage?: string | object | MessageFunction
21
+ onAuthSuccess?: (c: Context, username: string) => void | Promise<void>
22
+ }
23
+ | {
24
+ verifyUser: (username: string, password: string, c: Context) => boolean | Promise<boolean>
25
+ realm?: string
26
+ hashFunction?: Function
27
+ invalidUserMessage?: string | object | MessageFunction
28
+ onAuthSuccess?: (c: Context, username: string) => void | Promise<void>
29
+ }
30
+
31
+ /**
32
+ * Basic Auth Middleware for App.
33
+ *
34
+ *
35
+ * @param {BasicAuthOptions} options - The options for the basic authentication middleware.
36
+ * @param {string} options.username - The username for authentication.
37
+ * @param {string} options.password - The password for authentication.
38
+ * @param {string} [options.realm="Secure Area"] - The realm attribute for the WWW-Authenticate header.
39
+ * @param {Function} [options.hashFunction] - The hash function used for secure comparison.
40
+ * @param {Function} [options.verifyUser] - The function to verify user credentials.
41
+ * @param {string | object | MessageFunction} [options.invalidUserMessage="Unauthorized"] - The invalid user message.
42
+ * @param {Function} [options.onAuthSuccess] - Callback function called on successful authentication.
43
+ * @returns {MiddlewareHandler} The middleware handler function.
44
+ * @throws {HTTPException} If neither "username and password" nor "verifyUser" options are provided.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const app = new App()
49
+ *
50
+ * app.use(
51
+ * '/auth/*',
52
+ * basicAuth({
53
+ * username: process.env.BASIC_AUTH_USERNAME,
54
+ * password: process.env.BASIC_AUTH_PASSWORD,
55
+ * })
56
+ * )
57
+ *
58
+ * app.get('/auth/page', (c) => {
59
+ * return c.text('You are authorized')
60
+ * })
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * // With onAuthSuccess callback
66
+ * app.use(
67
+ * '/auth/*',
68
+ * basicAuth({
69
+ * username: process.env.BASIC_AUTH_USERNAME,
70
+ * password: process.env.BASIC_AUTH_PASSWORD,
71
+ * onAuthSuccess: (c, username) => {
72
+ * c.set('user', { name: username, role: 'admin' })
73
+ * console.log(`User ${username} authenticated`)
74
+ * },
75
+ * })
76
+ * )
77
+ * ```
78
+ */
79
+ export const basicAuth = (
80
+ options: BasicAuthOptions,
81
+ ...users: { username: string; password: string }[]
82
+ ): MiddlewareHandler => {
83
+ const usernamePasswordInOptions = 'username' in options && 'password' in options
84
+ const verifyUserInOptions = 'verifyUser' in options
85
+
86
+ if (!(usernamePasswordInOptions || verifyUserInOptions)) {
87
+ throw new Error(
88
+ 'basic auth middleware requires options for "username and password" or "verifyUser"'
89
+ )
90
+ }
91
+
92
+ if (!options.realm) {
93
+ options.realm = 'Secure Area'
94
+ }
95
+
96
+ if (!options.invalidUserMessage) {
97
+ options.invalidUserMessage = 'Unauthorized'
98
+ }
99
+
100
+ if (usernamePasswordInOptions) {
101
+ users.unshift({ username: options.username, password: options.password })
102
+ }
103
+
104
+ return async function basicAuth(ctx, next) {
105
+ const requestUser = auth(ctx.req.raw)
106
+ if (requestUser) {
107
+ if (verifyUserInOptions) {
108
+ if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
109
+ if (options.onAuthSuccess) {
110
+ await options.onAuthSuccess(ctx, requestUser.username)
111
+ }
112
+ await next()
113
+ return
114
+ }
115
+ } else {
116
+ for (const user of users) {
117
+ const [usernameEqual, passwordEqual] = await Promise.all([
118
+ timingSafeEqual(user.username, requestUser.username, options.hashFunction),
119
+ timingSafeEqual(user.password, requestUser.password, options.hashFunction),
120
+ ])
121
+ if (usernameEqual && passwordEqual) {
122
+ if (options.onAuthSuccess) {
123
+ await options.onAuthSuccess(ctx, requestUser.username)
124
+ }
125
+ await next()
126
+ return
127
+ }
128
+ }
129
+ }
130
+ }
131
+ // Invalid user.
132
+ const status = 401
133
+ const headers = {
134
+ 'WWW-Authenticate': 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"',
135
+ }
136
+ const responseMessage =
137
+ typeof options.invalidUserMessage === 'function'
138
+ ? await options.invalidUserMessage(ctx)
139
+ : options.invalidUserMessage
140
+ const res =
141
+ typeof responseMessage === 'string'
142
+ ? new Response(responseMessage, { status, headers })
143
+ : new Response(JSON.stringify(responseMessage), {
144
+ status,
145
+ headers: {
146
+ ...headers,
147
+ 'content-type': 'application/json',
148
+ },
149
+ })
150
+ throw new HTTPException(status, { res })
151
+ }
152
+ }