acrylblends 0.3.0 → 0.4.1

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 (341) hide show
  1. package/dist/index.d.ts +6 -1
  2. package/dist/index.js +84 -5
  3. package/dist/index.js.map +1 -1
  4. package/docs/framework/LICENSE +23 -0
  5. package/docs/framework/README.md +63 -0
  6. package/docs/framework/UPSTREAM.md +3 -0
  7. package/docs/framework/api-summary.md +138 -0
  8. package/docs/framework/concepts.md +105 -0
  9. package/docs/framework/context.md +129 -0
  10. package/docs/framework/getting-started.md +146 -0
  11. package/docs/framework/helpers.md +118 -0
  12. package/docs/framework/middleware.md +154 -0
  13. package/docs/framework/migration-from-0-3.md +108 -0
  14. package/docs/framework/migration-from-dsh-webserver.md +103 -0
  15. package/docs/framework/node-server.md +75 -0
  16. package/docs/framework/plugin-lifecycle.md +111 -0
  17. package/docs/framework/request.md +106 -0
  18. package/docs/framework/routing.md +188 -0
  19. package/docs/framework/surfaces.md +71 -0
  20. package/docs/framework/upstream.json +9 -0
  21. package/docs/framework/validation.md +135 -0
  22. package/package.json +4 -2
  23. package/plugins/acryl-inspect/plugin.json +2 -1
  24. package/plugins/acryl-inspect/src/report.ts +21 -13
  25. package/plugins/acryl-inspect/src/service.ts +9 -7
  26. package/plugins/acryl-inspect/tests/report.spec.ts +13 -8
  27. package/plugins/acryl-inspect/tests/service.spec.ts +11 -10
  28. package/plugins/acryl-inspect/upstream.json +2 -2
  29. package/plugins/acryl-node-server/LICENSE +26 -0
  30. package/plugins/acryl-node-server/plugin.json +2 -1
  31. package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
  32. package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
  33. package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
  34. package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
  35. package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
  36. package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
  37. package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
  38. package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
  39. package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
  40. package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
  41. package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
  42. package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
  43. package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
  44. package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
  45. package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
  46. package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
  47. package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
  48. package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
  49. package/plugins/acryl-node-server/src/index.ts +19 -6
  50. package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
  51. package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
  52. package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
  53. package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
  54. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
  55. package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
  56. package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
  57. package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
  58. package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
  59. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
  60. package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
  61. package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
  62. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
  63. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
  64. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
  65. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
  66. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
  67. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
  68. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
  69. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
  70. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
  71. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
  72. package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
  73. package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
  74. package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
  75. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
  76. package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
  77. package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
  78. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
  79. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
  80. package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
  81. package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
  82. package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
  83. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
  84. package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
  85. package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
  86. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
  87. package/plugins/acryl-node-server/tests/server.spec.ts +44 -8
  88. package/plugins/acryl-node-server/upstream.json +3 -3
  89. package/plugins/acryl-router/LICENSE +26 -0
  90. package/plugins/acryl-router/plugin.json +2 -1
  91. package/plugins/acryl-router/src/client.ts +2 -0
  92. package/plugins/acryl-router/src/connection.ts +42 -0
  93. package/plugins/acryl-router/src/core/app-base.ts +544 -0
  94. package/plugins/acryl-router/src/core/app.test.ts +3833 -0
  95. package/plugins/acryl-router/src/core/app.ts +34 -0
  96. package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
  97. package/plugins/acryl-router/src/core/client/client.ts +249 -0
  98. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
  99. package/plugins/acryl-router/src/core/client/index.ts +17 -0
  100. package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
  101. package/plugins/acryl-router/src/core/client/types.ts +393 -0
  102. package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
  103. package/plugins/acryl-router/src/core/client/utils.ts +117 -0
  104. package/plugins/acryl-router/src/core/compose.test.ts +751 -0
  105. package/plugins/acryl-router/src/core/compose.ts +73 -0
  106. package/plugins/acryl-router/src/core/context.test.ts +629 -0
  107. package/plugins/acryl-router/src/core/context.ts +781 -0
  108. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
  109. package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
  110. package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
  111. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
  112. package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
  113. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
  114. package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
  115. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
  116. package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
  117. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
  118. package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
  119. package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
  120. package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
  121. package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
  122. package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
  123. package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
  124. package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
  125. package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
  126. package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
  127. package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
  128. package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
  129. package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
  130. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
  131. package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
  132. package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
  133. package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
  134. package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
  135. package/plugins/acryl-router/src/core/http-exception.ts +77 -0
  136. package/plugins/acryl-router/src/core/index.ts +53 -0
  137. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
  138. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
  139. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
  140. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
  141. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
  142. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
  143. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
  144. package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
  145. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
  146. package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
  147. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
  148. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
  149. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
  150. package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
  151. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
  152. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
  153. package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
  154. package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
  155. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
  156. package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
  157. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
  158. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
  159. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
  160. package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
  161. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
  162. package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
  163. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
  164. package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
  165. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
  166. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
  167. package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
  168. package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
  169. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
  170. package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
  171. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
  172. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
  173. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
  174. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
  175. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
  176. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
  177. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
  178. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
  179. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
  180. package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
  181. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
  182. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
  183. package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
  184. package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
  185. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
  186. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
  187. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
  188. package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
  189. package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
  190. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
  191. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
  192. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
  193. package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
  194. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
  195. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
  196. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
  197. package/plugins/acryl-router/src/core/request/constants.ts +1 -0
  198. package/plugins/acryl-router/src/core/request.test.ts +751 -0
  199. package/plugins/acryl-router/src/core/request.ts +502 -0
  200. package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
  201. package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
  202. package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
  203. package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
  204. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
  205. package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
  206. package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
  207. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
  208. package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
  209. package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
  210. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
  211. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
  212. package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
  213. package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
  214. package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
  215. package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
  216. package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
  217. package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
  218. package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
  219. package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
  220. package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
  221. package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
  222. package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
  223. package/plugins/acryl-router/src/core/router/utils.ts +1 -0
  224. package/plugins/acryl-router/src/core/router.ts +103 -0
  225. package/plugins/acryl-router/src/core/types.test.ts +4134 -0
  226. package/plugins/acryl-router/src/core/types.ts +2782 -0
  227. package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
  228. package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
  229. package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
  230. package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
  231. package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
  232. package/plugins/acryl-router/src/core/utils/body.ts +263 -0
  233. package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
  234. package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
  235. package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
  236. package/plugins/acryl-router/src/core/utils/color.ts +56 -0
  237. package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
  238. package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
  239. package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
  240. package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
  241. package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
  242. package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
  243. package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
  244. package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
  245. package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
  246. package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
  247. package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
  248. package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
  249. package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
  250. package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
  251. package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
  252. package/plugins/acryl-router/src/core/utils/html.ts +182 -0
  253. package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
  254. package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
  255. package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
  256. package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
  257. package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
  258. package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
  259. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
  260. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
  261. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
  262. package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
  263. package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
  264. package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
  265. package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
  266. package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
  267. package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
  268. package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
  269. package/plugins/acryl-router/src/core/utils/types.ts +123 -0
  270. package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
  271. package/plugins/acryl-router/src/core/utils/url.ts +337 -0
  272. package/plugins/acryl-router/src/core/validator/index.ts +8 -0
  273. package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
  274. package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
  275. package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
  276. package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
  277. package/plugins/acryl-router/src/helpers/index.ts +13 -3
  278. package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
  279. package/plugins/acryl-router/src/index.ts +6 -6
  280. package/plugins/acryl-router/src/middleware/index.ts +25 -6
  281. package/plugins/acryl-router/src/middleware/loopback-only.ts +53 -14
  282. package/plugins/acryl-router/src/service.ts +262 -64
  283. package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
  284. package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
  285. package/plugins/acryl-router/tests/loader.spec.ts +3 -2
  286. package/plugins/acryl-router/tests/loopback-only.spec.ts +80 -0
  287. package/plugins/acryl-router/tests/service.spec.ts +281 -66
  288. package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
  289. package/plugins/acryl-router/upstream.json +2 -2
  290. package/plugins/acryl-router-http/plugin.json +2 -1
  291. package/plugins/acryl-router-http/src/bridge.ts +3 -1
  292. package/plugins/acryl-router-http/tests/adapter.spec.ts +16 -12
  293. package/plugins/acryl-router-http/tests/surfaces.spec.ts +12 -10
  294. package/plugins/acryl-router-http/upstream.json +3 -3
  295. package/plugins/acryl-state/NOTICE +30 -0
  296. package/plugins/acryl-state/plugin.json +1 -1
  297. package/plugins/acryl-state/src/cell.ts +1 -1
  298. package/plugins/acryl-state/src/service.ts +33 -15
  299. package/plugins/acryl-state/upstream.json +6 -4
  300. package/plugins/builder/script.ts +4 -7
  301. package/plugins/extensions/index.ts +6 -5
  302. package/plugins/extensions/resolve.ts +28 -3
  303. package/plugins/openai/prompt.ts +9 -7
  304. package/plugins/tsconfig.json +5 -4
  305. package/shared/AGENTS.core.md +54 -0
  306. package/templates/agent/AGENTS.md +6 -0
  307. package/templates/agent/README.md +2 -2
  308. package/templates/agent/blend.yaml +1 -1
  309. package/templates/agent/src/routes.ts +37 -27
  310. package/templates/agent/test/model.test.ts +2 -1
  311. package/templates/agent/tsconfig.json +8 -5
  312. package/templates/blank/AGENTS.md +5 -0
  313. package/templates/blank/README.md +1 -1
  314. package/templates/blank/src/routes.ts +6 -4
  315. package/templates/blank/tsconfig.json +2 -4
  316. package/templates/todo/AGENTS.md +5 -0
  317. package/templates/todo/src/page.ts +1 -1
  318. package/templates/todo/src/todo.ts +58 -29
  319. package/templates/todo/tsconfig.json +2 -4
  320. package/templates/todo/upstream.json +2 -2
  321. package/plugins/acryl-router/src/compose.ts +0 -21
  322. package/plugins/acryl-router/src/context.ts +0 -59
  323. package/plugins/acryl-router/src/helpers/read-body.ts +0 -59
  324. package/plugins/acryl-router/src/helpers/sse.ts +0 -83
  325. package/plugins/acryl-router/src/helpers/validate.ts +0 -44
  326. package/plugins/acryl-router/src/http-error.ts +0 -21
  327. package/plugins/acryl-router/src/middleware/body-limit.ts +0 -25
  328. package/plugins/acryl-router/src/middleware/cors.ts +0 -46
  329. package/plugins/acryl-router/src/middleware/logger.ts +0 -21
  330. package/plugins/acryl-router/src/middleware/request-id.ts +0 -24
  331. package/plugins/acryl-router/src/middleware/secure-headers.ts +0 -23
  332. package/plugins/acryl-router/src/pattern.ts +0 -89
  333. package/plugins/acryl-router/src/registrar.ts +0 -90
  334. package/plugins/acryl-router/src/table.ts +0 -156
  335. package/plugins/acryl-router/src/types.ts +0 -73
  336. package/plugins/acryl-router/src/util.ts +0 -23
  337. package/plugins/acryl-router/tests/api.spec.ts +0 -223
  338. package/plugins/acryl-router/tests/conformance.ts +0 -170
  339. package/plugins/acryl-router/tests/helpers.spec.ts +0 -172
  340. package/plugins/acryl-router/tests/middleware.spec.ts +0 -183
  341. package/plugins/acryl-router/tests/table.spec.ts +0 -47
@@ -0,0 +1,355 @@
1
+ import { every, except, some } from './index.ts'
2
+ import { App } from '../../app.ts'
3
+ import type { MiddlewareHandler } from '../../types.ts'
4
+
5
+ const nextMiddleware: MiddlewareHandler = async (_, next) => await next()
6
+
7
+ describe('some', () => {
8
+ let app: App
9
+
10
+ beforeEach(() => {
11
+ app = new App()
12
+ })
13
+
14
+ it('Should call only the first middleware', async () => {
15
+ const middleware1 = vi.fn(nextMiddleware)
16
+ const middleware2 = vi.fn(nextMiddleware)
17
+
18
+ app.use('/', some(middleware1, middleware2))
19
+ app.get('/', (c) => {
20
+ return c.text('Hello World')
21
+ })
22
+ const res = await app.request('http://localhost/')
23
+
24
+ expect(middleware1).toBeCalled()
25
+ expect(middleware2).not.toBeCalled()
26
+ expect(await res.text()).toBe('Hello World')
27
+ })
28
+
29
+ it('Should try to call the second middleware if the first one throws an error', async () => {
30
+ const middleware1 = () => {
31
+ throw new Error('Error')
32
+ }
33
+ const middleware2 = vi.fn(nextMiddleware)
34
+
35
+ app.use('/', some(middleware1, middleware2))
36
+ app.get('/', (c) => {
37
+ return c.text('Hello World')
38
+ })
39
+ const res = await app.request('http://localhost/')
40
+
41
+ expect(middleware2).toBeCalled()
42
+ expect(await res.text()).toBe('Hello World')
43
+ })
44
+
45
+ it('Should try to call the second middleware if the first one returns false', async () => {
46
+ const middleware1 = () => false
47
+ const middleware2 = vi.fn(nextMiddleware)
48
+
49
+ app.use('/', some(middleware1, middleware2))
50
+ app.get('/', (c) => {
51
+ return c.text('Hello World')
52
+ })
53
+ const res = await app.request('http://localhost/')
54
+
55
+ expect(middleware2).toBeCalled()
56
+ expect(await res.text()).toBe('Hello World')
57
+ })
58
+
59
+ it('Should throw last error if all middleware throw an error', async () => {
60
+ const middleware1 = () => {
61
+ throw new Error('Error1')
62
+ }
63
+ const middleware2 = () => {
64
+ throw new Error('Error2')
65
+ }
66
+
67
+ app.use('/', some(middleware1, middleware2))
68
+ app.get('/', (c) => {
69
+ return c.text('Hello World')
70
+ })
71
+ app.onError((error, c) => {
72
+ return c.text(error.message)
73
+ })
74
+ const res = await app.request('http://localhost/')
75
+
76
+ expect(await res.text()).toBe('Error2')
77
+ })
78
+
79
+ it('Should throw error if all middleware return false', async () => {
80
+ const middleware1 = () => false
81
+ const middleware2 = () => false
82
+
83
+ app.use('/', some(middleware1, middleware2))
84
+ app.get('/', (c) => {
85
+ return c.text('Hello World')
86
+ })
87
+ app.onError((_, c) => {
88
+ return c.text('oops')
89
+ })
90
+ const res = await app.request('http://localhost/')
91
+
92
+ expect(await res.text()).toBe('oops')
93
+ })
94
+
95
+ it('Should not call skipped middleware even if an error is thrown', async () => {
96
+ const middleware1: MiddlewareHandler = async (_c, next) => {
97
+ await next()
98
+ }
99
+ const middleware2 = vi.fn(() => true)
100
+
101
+ app.use(
102
+ '/',
103
+ every(some(middleware1, middleware2), () => {
104
+ throw new Error('Error')
105
+ })
106
+ )
107
+ app.get('/', (c) => c.text('OK'))
108
+ app.onError((_, c) => {
109
+ return c.text('oops')
110
+ })
111
+ const res = await app.request('http://localhost/')
112
+
113
+ expect(middleware2).not.toBeCalled()
114
+ expect(await res.text()).toBe('oops')
115
+ })
116
+
117
+ it('Should not call skipped middleware even if an error is thrown with returning truthy value middleware', async () => {
118
+ const middleware1 = () => true
119
+ const middleware2 = vi.fn(() => true)
120
+
121
+ app.use(
122
+ '/',
123
+ every(some(middleware1, middleware2), () => {
124
+ throw new Error('Error')
125
+ })
126
+ )
127
+ app.get('/', (c) => c.text('OK'))
128
+ app.onError((_, c) => {
129
+ return c.text('oops')
130
+ })
131
+ const res = await app.request('http://localhost/')
132
+
133
+ expect(middleware2).not.toBeCalled()
134
+ expect(await res.text()).toBe('oops')
135
+ })
136
+
137
+ it('Should return a Response from a middleware that short-circuits', async () => {
138
+ const shortCircuit: MiddlewareHandler = async (c) => c.json({ error: 'bad request' }, 400)
139
+ const next = vi.fn(async (_c, n) => {
140
+ await n()
141
+ })
142
+
143
+ const app = new App()
144
+ app.use('/', some(shortCircuit, next))
145
+ app.get('/', (c) => c.text('handler'))
146
+
147
+ const res = await app.request('http://localhost/')
148
+
149
+ expect(res.status).toBe(400)
150
+ expect(await res.json()).toEqual({ error: 'bad request' })
151
+ expect(next).not.toBeCalled()
152
+ })
153
+ })
154
+
155
+ describe('every', () => {
156
+ let app: App
157
+
158
+ beforeEach(() => {
159
+ app = new App()
160
+ })
161
+
162
+ it('Should call all middleware', async () => {
163
+ const middleware1 = vi.fn(nextMiddleware)
164
+ const middleware2 = vi.fn(nextMiddleware)
165
+
166
+ app.use('/', every(middleware1, middleware2))
167
+ app.get('/', (c) => {
168
+ return c.text('Hello World')
169
+ })
170
+ const res = await app.request('http://localhost/')
171
+
172
+ expect(middleware1).toBeCalled()
173
+ expect(middleware2).toBeCalled()
174
+ expect(await res.text()).toBe('Hello World')
175
+ })
176
+
177
+ it('Should throw error if any middleware throws an error', async () => {
178
+ const middleware1 = () => {
179
+ throw new Error('Error1')
180
+ }
181
+ const middleware2 = vi.fn(nextMiddleware)
182
+
183
+ app.use('/', every(middleware1, middleware2))
184
+ app.get('/', (c) => {
185
+ return c.text('Hello World')
186
+ })
187
+ app.onError((error, c) => {
188
+ return c.text(error.message)
189
+ })
190
+ const res = await app.request('http://localhost/')
191
+
192
+ expect(await res.text()).toBe('Error1')
193
+ expect(middleware2).not.toBeCalled()
194
+ })
195
+
196
+ it('Should throw error if any middleware returns false', async () => {
197
+ const middleware1 = () => false
198
+ const middleware2 = vi.fn(nextMiddleware)
199
+
200
+ app.use('/', every(middleware1, middleware2))
201
+ app.get('/', (c) => {
202
+ return c.text('Hello World')
203
+ })
204
+ app.onError((_, c) => {
205
+ return c.text('oops')
206
+ })
207
+ const res = await app.request('http://localhost/')
208
+
209
+ expect(await res.text()).toBe('oops')
210
+ expect(middleware2).not.toBeCalled()
211
+ })
212
+
213
+ it('Should return the same response a middleware returns if it short-circuits the chain', async () => {
214
+ const middleware1: MiddlewareHandler = async (c) => {
215
+ return c.text('Hello Middleware 1')
216
+ }
217
+ const middleware2 = vi.fn(nextMiddleware)
218
+
219
+ app.use('/', every(middleware1, middleware2))
220
+ app.get('/', (c) => {
221
+ return c.text('Hello World')
222
+ })
223
+ const res = await app.request('http://localhost/')
224
+
225
+ expect(await res.text()).toBe('Hello Middleware 1')
226
+ expect(middleware2).not.toBeCalled()
227
+ })
228
+
229
+ it('Should pass the path params to middlewares', async () => {
230
+ const app = new App()
231
+ app.use('*', nextMiddleware)
232
+ const paramMiddleware: MiddlewareHandler = async (c) => {
233
+ return c.json(c.req.param(), 200)
234
+ }
235
+
236
+ app.use('/:id', every(paramMiddleware))
237
+ app.get('/:id', (c) => {
238
+ return c.text('Hello World')
239
+ })
240
+
241
+ const res = await app.request('http://localhost/123')
242
+ expect(await res.json()).toEqual({ id: '123' })
243
+ })
244
+ })
245
+
246
+ describe('except', () => {
247
+ let app: App
248
+
249
+ beforeEach(() => {
250
+ app = new App()
251
+ })
252
+
253
+ it('Should call all middleware, except the one that matches the condition', async () => {
254
+ const middleware1 = vi.fn(nextMiddleware)
255
+ const middleware2 = vi.fn(nextMiddleware)
256
+
257
+ app.use('*', except('/maintenance', middleware1, middleware2))
258
+ app.get('/maintenance', (c) => {
259
+ return c.text('Hello Maintenance')
260
+ })
261
+ app.get('*', (c) => {
262
+ return c.redirect('/maintenance')
263
+ })
264
+ let res = await app.request('http://localhost/')
265
+
266
+ expect(middleware1).toBeCalled()
267
+ expect(middleware2).toBeCalled()
268
+ expect(res.headers.get('location')).toBe('/maintenance')
269
+
270
+ middleware1.mockClear()
271
+ middleware2.mockClear()
272
+ res = await app.request('http://localhost/maintenance')
273
+
274
+ expect(middleware1).not.toBeCalled()
275
+ expect(middleware2).not.toBeCalled()
276
+ expect(await res.text()).toBe('Hello Maintenance')
277
+ })
278
+
279
+ it('Should call all middleware, except the one that matches some of the conditions', async () => {
280
+ const middleware1 = vi.fn(nextMiddleware)
281
+ const middleware2 = vi.fn(nextMiddleware)
282
+
283
+ app.use('*', except(['/maintenance', '/public/users/:id'], middleware1, middleware2))
284
+ app.get('/maintenance', (c) => {
285
+ return c.text('Hello Maintenance')
286
+ })
287
+ app.get('/public/users/:id', (c) => {
288
+ return c.text(`Hello Public User ${c.req.param('id')}`)
289
+ })
290
+ app.get('/secret', (c) => {
291
+ return c.text('Hello Secret')
292
+ })
293
+ let res = await app.request('http://localhost/secret')
294
+
295
+ expect(middleware1).toBeCalled()
296
+ expect(middleware2).toBeCalled()
297
+ expect(await res.text()).toBe('Hello Secret')
298
+
299
+ middleware1.mockClear()
300
+ middleware2.mockClear()
301
+ res = await app.request('http://localhost/maintenance')
302
+
303
+ expect(middleware1).not.toBeCalled()
304
+ expect(middleware2).not.toBeCalled()
305
+ expect(await res.text()).toBe('Hello Maintenance')
306
+
307
+ middleware1.mockClear()
308
+ middleware2.mockClear()
309
+ res = await app.request('http://localhost/public/users/123')
310
+
311
+ expect(middleware1).not.toBeCalled()
312
+ expect(middleware2).not.toBeCalled()
313
+ expect(await res.text()).toBe('Hello Public User 123')
314
+ })
315
+
316
+ it('Should call all middleware, except the one that matches some of the condition function', async () => {
317
+ const middleware1 = vi.fn(nextMiddleware)
318
+ const middleware2 = vi.fn(nextMiddleware)
319
+
320
+ app.use(
321
+ '*',
322
+ except(['/maintenance', (c) => !!c.req.path.match(/public/)], middleware1, middleware2)
323
+ )
324
+ app.get('/maintenance', (c) => {
325
+ return c.text('Hello Maintenance')
326
+ })
327
+ app.get('/public/users/:id', (c) => {
328
+ return c.text(`Hello Public User ${c.req.param('id')}`)
329
+ })
330
+ app.get('/secret', (c) => {
331
+ return c.text('Hello Secret')
332
+ })
333
+ let res = await app.request('http://localhost/secret')
334
+
335
+ expect(middleware1).toBeCalled()
336
+ expect(middleware2).toBeCalled()
337
+ expect(await res.text()).toBe('Hello Secret')
338
+
339
+ middleware1.mockClear()
340
+ middleware2.mockClear()
341
+ res = await app.request('http://localhost/maintenance')
342
+
343
+ expect(middleware1).not.toBeCalled()
344
+ expect(middleware2).not.toBeCalled()
345
+ expect(await res.text()).toBe('Hello Maintenance')
346
+
347
+ middleware1.mockClear()
348
+ middleware2.mockClear()
349
+ res = await app.request('http://localhost/public/users/123')
350
+
351
+ expect(middleware1).not.toBeCalled()
352
+ expect(middleware2).not.toBeCalled()
353
+ expect(await res.text()).toBe('Hello Public User 123')
354
+ })
355
+ })
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @module
3
+ * Combine Middleware for App.
4
+ */
5
+
6
+ import { compose } from '../../compose.ts'
7
+ import type { Context } from '../../context.ts'
8
+ import { METHOD_NAME_ALL } from '../../router.ts'
9
+ import { TrieRouter } from '../../router/trie-router/index.ts'
10
+ import type { MiddlewareHandler, Next } from '../../types.ts'
11
+
12
+ type Condition = (c: Context) => boolean
13
+
14
+ /**
15
+ * Create a composed middleware that runs the first middleware that returns true.
16
+ *
17
+ * @param middleware - An array of MiddlewareHandler or Condition functions.
18
+ * Middleware is applied in the order it is passed, and if any middleware exits without returning
19
+ * an exception first, subsequent middleware will not be executed.
20
+ * You can also pass a condition function that returns a boolean value. If returns true
21
+ * the evaluation will be halted, and rest of the middleware will not be executed.
22
+ * @returns A composed middleware.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { some } from 'acryl-router/middleware'
27
+ * import { bearerAuth } from 'acryl-router/middleware'
28
+ * import { myRateLimit } from '@/rate-limit'
29
+ *
30
+ * // If client has a valid token, then skip rate limiting.
31
+ * // Otherwise, apply rate limiting.
32
+ * app.use('/api/*', some(
33
+ * bearerAuth({ token }),
34
+ * myRateLimit({ limit: 100 }),
35
+ * ));
36
+ * ```
37
+ */
38
+ export const some = (...middleware: (MiddlewareHandler | Condition)[]): MiddlewareHandler => {
39
+ return async function some(c, next) {
40
+ let isNextCalled = false
41
+ const wrappedNext = () => {
42
+ isNextCalled = true
43
+ return next()
44
+ }
45
+
46
+ let lastError: unknown
47
+ let response: Response | undefined
48
+ for (const handler of middleware) {
49
+ try {
50
+ const result = await handler(c, wrappedNext)
51
+ if (result === true && !c.finalized) {
52
+ await wrappedNext()
53
+ } else if (result === false) {
54
+ lastError = new Error('No successful middleware found')
55
+ continue
56
+ } else if (result && result !== true) {
57
+ response = result
58
+ }
59
+ lastError = undefined
60
+ break
61
+ } catch (error) {
62
+ lastError = error
63
+ if (isNextCalled) {
64
+ break
65
+ }
66
+ }
67
+ }
68
+ if (lastError) {
69
+ throw lastError
70
+ }
71
+ return response
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Create a composed middleware that runs all middleware and throws an error if any of them fail.
77
+ *
78
+ * @param middleware - An array of MiddlewareHandler or Condition functions.
79
+ * Middleware is applied in the order it is passed, and if any middleware throws an error,
80
+ * subsequent middleware will not be executed.
81
+ * You can also pass a condition function that returns a boolean value. If returns false
82
+ * the evaluation will be halted, and rest of the middleware will not be executed.
83
+ * @returns A composed middleware.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { some, every } from 'acryl-router/middleware'
88
+ * import { bearerAuth } from 'acryl-router/middleware'
89
+ * import { myCheckLocalNetwork } from '@/check-local-network'
90
+ * import { myRateLimit } from '@/rate-limit'
91
+ *
92
+ * // If client is in local network, then skip authentication and rate limiting.
93
+ * // Otherwise, apply authentication and rate limiting.
94
+ * app.use('/api/*', some(
95
+ * myCheckLocalNetwork(),
96
+ * every(
97
+ * bearerAuth({ token }),
98
+ * myRateLimit({ limit: 100 }),
99
+ * ),
100
+ * ));
101
+ * ```
102
+ */
103
+ export const every = (...middleware: (MiddlewareHandler | Condition)[]): MiddlewareHandler => {
104
+ return async function every(c, next) {
105
+ const currentRouteIndex = c.req.routeIndex
106
+ await compose(
107
+ middleware.map((m) => [
108
+ [
109
+ async (c: Context, next: Next) => {
110
+ c.req.routeIndex = currentRouteIndex // should be unchanged in this context
111
+ const res = await m(c, next)
112
+ if (res === false) {
113
+ throw new Error('Unmet condition')
114
+ }
115
+ return res
116
+ },
117
+ ],
118
+ ])
119
+ )(c, next)
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Create a composed middleware that runs all middleware except when the condition is met.
125
+ *
126
+ * @param condition - A string or Condition function.
127
+ * If there are multiple targets to match any of them, they can be passed as an array.
128
+ * If a string is passed, it will be treated as a path pattern to match.
129
+ * If a Condition function is passed, it will be evaluated against the request context.
130
+ * @param middleware - Middleware to run when the condition is not met.
131
+ * Multiple middleware can be passed, and they are applied in the order they are passed.
132
+ * @returns A composed middleware.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * import { except } from 'acryl-router/middleware'
137
+ * import { bearerAuth } from 'acryl-router/middleware'
138
+ *
139
+ * // If client is accessing public API, then skip authentication.
140
+ * // Otherwise, require a valid token.
141
+ * app.use('/api/*', except(
142
+ * '/api/public/*',
143
+ * bearerAuth({ token }),
144
+ * ));
145
+ * ```
146
+ */
147
+ export const except = (
148
+ condition: string | Condition | (string | Condition)[],
149
+ ...middleware: MiddlewareHandler[]
150
+ ): MiddlewareHandler => {
151
+ let router: TrieRouter<true> | undefined = undefined
152
+ const conditions = (Array.isArray(condition) ? condition : [condition])
153
+ .map((condition) => {
154
+ if (typeof condition === 'string') {
155
+ router ||= new TrieRouter()
156
+ router.add(METHOD_NAME_ALL, condition, true)
157
+ } else {
158
+ return condition
159
+ }
160
+ })
161
+ .filter(Boolean) as Condition[]
162
+
163
+ if (router) {
164
+ conditions.unshift((c: Context) => !!router?.match(METHOD_NAME_ALL, c.req.path)?.[0]?.[0]?.[0])
165
+ }
166
+
167
+ const handler = some((c: Context) => conditions.some((cond) => cond(c)), every(...middleware))
168
+ return async function except(c, next) {
169
+ await handler(c, next)
170
+ }
171
+ }