acrylblends 0.2.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 (335) hide show
  1. package/dist/index.d.ts +22 -16
  2. package/dist/index.js +65 -20
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/acryl-inspect/LICENSE +21 -0
  6. package/plugins/acryl-inspect/plugin.json +12 -0
  7. package/plugins/acryl-inspect/src/index.ts +3 -0
  8. package/plugins/acryl-inspect/src/report.ts +126 -0
  9. package/plugins/acryl-inspect/src/service.ts +68 -0
  10. package/plugins/acryl-inspect/tests/report.spec.ts +63 -0
  11. package/plugins/acryl-inspect/tests/service.spec.ts +121 -0
  12. package/plugins/acryl-inspect/upstream.json +18 -0
  13. package/plugins/acryl-node-server/LICENSE +47 -0
  14. package/plugins/acryl-node-server/plugin.json +13 -0
  15. package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
  16. package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
  17. package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
  18. package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
  19. package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
  20. package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
  21. package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
  22. package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
  23. package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
  24. package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
  25. package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
  26. package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
  27. package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
  28. package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
  29. package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
  30. package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
  31. package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
  32. package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
  33. package/plugins/acryl-node-server/src/index.ts +107 -0
  34. package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
  35. package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
  36. package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
  37. package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
  38. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
  39. package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
  40. package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
  41. package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
  42. package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
  43. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
  44. package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
  45. package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
  46. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
  47. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
  48. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
  49. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
  50. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
  51. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
  52. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
  53. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
  54. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
  55. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
  56. package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
  57. package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
  58. package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
  59. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
  60. package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
  61. package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
  62. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
  63. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
  64. package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
  65. package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
  66. package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
  67. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
  68. package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
  69. package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
  70. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
  71. package/plugins/acryl-node-server/tests/server.spec.ts +141 -0
  72. package/plugins/acryl-node-server/upstream.json +18 -0
  73. package/plugins/acryl-router/LICENSE +47 -0
  74. package/plugins/acryl-router/plugin.json +13 -0
  75. package/plugins/acryl-router/src/client.ts +2 -0
  76. package/plugins/acryl-router/src/connection.ts +42 -0
  77. package/plugins/acryl-router/src/core/app-base.ts +544 -0
  78. package/plugins/acryl-router/src/core/app.test.ts +3833 -0
  79. package/plugins/acryl-router/src/core/app.ts +34 -0
  80. package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
  81. package/plugins/acryl-router/src/core/client/client.ts +249 -0
  82. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
  83. package/plugins/acryl-router/src/core/client/index.ts +17 -0
  84. package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
  85. package/plugins/acryl-router/src/core/client/types.ts +393 -0
  86. package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
  87. package/plugins/acryl-router/src/core/client/utils.ts +117 -0
  88. package/plugins/acryl-router/src/core/compose.test.ts +751 -0
  89. package/plugins/acryl-router/src/core/compose.ts +73 -0
  90. package/plugins/acryl-router/src/core/context.test.ts +629 -0
  91. package/plugins/acryl-router/src/core/context.ts +781 -0
  92. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
  93. package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
  94. package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
  95. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
  96. package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
  97. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
  98. package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
  99. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
  100. package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
  101. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
  102. package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
  103. package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
  104. package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
  105. package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
  106. package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
  107. package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
  108. package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
  109. package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
  110. package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
  111. package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
  112. package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
  113. package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
  114. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
  115. package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
  116. package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
  117. package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
  118. package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
  119. package/plugins/acryl-router/src/core/http-exception.ts +77 -0
  120. package/plugins/acryl-router/src/core/index.ts +53 -0
  121. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
  122. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
  123. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
  124. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
  125. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
  126. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
  127. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
  128. package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
  129. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
  130. package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
  131. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
  132. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
  133. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
  134. package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
  135. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
  136. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
  137. package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
  138. package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
  139. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
  140. package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
  141. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
  142. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
  143. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
  144. package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
  145. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
  146. package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
  147. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
  148. package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
  149. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
  150. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
  151. package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
  152. package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
  153. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
  154. package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
  155. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
  156. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
  157. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
  158. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
  159. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
  160. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
  161. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
  162. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
  163. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
  164. package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
  165. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
  166. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
  167. package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
  168. package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
  169. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
  170. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
  171. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
  172. package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
  173. package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
  174. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
  175. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
  176. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
  177. package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
  178. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
  179. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
  180. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
  181. package/plugins/acryl-router/src/core/request/constants.ts +1 -0
  182. package/plugins/acryl-router/src/core/request.test.ts +751 -0
  183. package/plugins/acryl-router/src/core/request.ts +502 -0
  184. package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
  185. package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
  186. package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
  187. package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
  188. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
  189. package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
  190. package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
  191. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
  192. package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
  193. package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
  194. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
  195. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
  196. package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
  197. package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
  198. package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
  199. package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
  200. package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
  201. package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
  202. package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
  203. package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
  204. package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
  205. package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
  206. package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
  207. package/plugins/acryl-router/src/core/router/utils.ts +1 -0
  208. package/plugins/acryl-router/src/core/router.ts +103 -0
  209. package/plugins/acryl-router/src/core/types.test.ts +4134 -0
  210. package/plugins/acryl-router/src/core/types.ts +2782 -0
  211. package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
  212. package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
  213. package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
  214. package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
  215. package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
  216. package/plugins/acryl-router/src/core/utils/body.ts +263 -0
  217. package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
  218. package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
  219. package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
  220. package/plugins/acryl-router/src/core/utils/color.ts +56 -0
  221. package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
  222. package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
  223. package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
  224. package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
  225. package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
  226. package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
  227. package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
  228. package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
  229. package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
  230. package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
  231. package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
  232. package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
  233. package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
  234. package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
  235. package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
  236. package/plugins/acryl-router/src/core/utils/html.ts +182 -0
  237. package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
  238. package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
  239. package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
  240. package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
  241. package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
  242. package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
  243. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
  244. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
  245. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
  246. package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
  247. package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
  248. package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
  249. package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
  250. package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
  251. package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
  252. package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
  253. package/plugins/acryl-router/src/core/utils/types.ts +123 -0
  254. package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
  255. package/plugins/acryl-router/src/core/utils/url.ts +337 -0
  256. package/plugins/acryl-router/src/core/validator/index.ts +8 -0
  257. package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
  258. package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
  259. package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
  260. package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
  261. package/plugins/acryl-router/src/helpers/index.ts +13 -0
  262. package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
  263. package/plugins/acryl-router/src/index.ts +6 -0
  264. package/plugins/acryl-router/src/middleware/index.ts +25 -0
  265. package/plugins/acryl-router/src/middleware/loopback-only.ts +88 -0
  266. package/plugins/acryl-router/src/service.ts +356 -0
  267. package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
  268. package/plugins/acryl-router/tests/live-install.spec.ts +64 -0
  269. package/plugins/acryl-router/tests/loader.spec.ts +72 -0
  270. package/plugins/acryl-router/tests/service.spec.ts +409 -0
  271. package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
  272. package/plugins/acryl-router/upstream.json +20 -0
  273. package/plugins/acryl-router-http/LICENSE +21 -0
  274. package/plugins/acryl-router-http/plugin.json +12 -0
  275. package/plugins/acryl-router-http/src/bridge.ts +54 -0
  276. package/plugins/acryl-router-http/src/index.ts +63 -0
  277. package/plugins/acryl-router-http/src/serve.ts +24 -0
  278. package/plugins/acryl-router-http/tests/adapter.spec.ts +174 -0
  279. package/plugins/acryl-router-http/tests/stream.spec.ts +133 -0
  280. package/plugins/acryl-router-http/tests/surfaces.spec.ts +101 -0
  281. package/plugins/acryl-router-http/upstream.json +22 -0
  282. package/plugins/acryl-state/LICENSE +21 -0
  283. package/plugins/acryl-state/NOTICE +30 -0
  284. package/plugins/acryl-state/plugin.json +12 -0
  285. package/plugins/acryl-state/src/cell.ts +67 -0
  286. package/plugins/acryl-state/src/index.ts +3 -0
  287. package/plugins/acryl-state/src/react.ts +11 -0
  288. package/plugins/acryl-state/src/service.ts +119 -0
  289. package/plugins/acryl-state/tests/cell.spec.ts +71 -0
  290. package/plugins/acryl-state/tests/react.spec.ts +39 -0
  291. package/plugins/acryl-state/tests/service.spec.ts +132 -0
  292. package/plugins/acryl-state/upstream.json +22 -0
  293. package/plugins/builder/script.ts +6 -10
  294. package/plugins/extensions/index.ts +20 -3
  295. package/plugins/extensions/resolve.ts +28 -3
  296. package/plugins/openai/prompt.ts +12 -6
  297. package/plugins/tasks/index.ts +14 -0
  298. package/plugins/tsconfig.json +14 -5
  299. package/templates/agent/blend.yaml +5 -7
  300. package/templates/agent/src/app.ts +8 -8
  301. package/templates/agent/src/routes.ts +39 -38
  302. package/templates/agent/template.json +3 -3
  303. package/templates/agent/test/builder.test.ts +22 -14
  304. package/templates/agent/test/model.test.ts +3 -3
  305. package/templates/agent/tsconfig.json +8 -5
  306. package/templates/{app → blank}/blend.yaml +3 -3
  307. package/templates/{app → blank}/src/app.ts +5 -5
  308. package/templates/blank/src/routes.ts +16 -0
  309. package/templates/blank/template.json +1 -0
  310. package/templates/{app → blank}/test/app.test.ts +1 -1
  311. package/templates/{app → blank}/tsconfig.json +2 -4
  312. package/templates/todo/README.md +27 -0
  313. package/templates/todo/blend.yaml +25 -0
  314. package/templates/todo/gitignore +2 -0
  315. package/templates/todo/package.json +23 -0
  316. package/templates/todo/src/app.ts +71 -0
  317. package/templates/todo/src/main.ts +19 -0
  318. package/templates/todo/src/page.ts +28 -0
  319. package/templates/todo/src/todo.ts +123 -0
  320. package/templates/todo/template.json +1 -0
  321. package/templates/todo/test/todo.test.ts +145 -0
  322. package/templates/todo/tsconfig.json +17 -0
  323. package/templates/todo/upstream.json +12 -0
  324. package/plugins/events/index.ts +0 -42
  325. package/plugins/events/plugin.json +0 -9
  326. package/plugins/http/index.ts +0 -64
  327. package/plugins/http/plugin.json +0 -10
  328. package/plugins/server/index.ts +0 -138
  329. package/plugins/server/plugin.json +0 -10
  330. package/templates/app/src/routes.ts +0 -14
  331. package/templates/app/template.json +0 -1
  332. /package/templates/{app → blank}/README.md +0 -0
  333. /package/templates/{app → blank}/gitignore +0 -0
  334. /package/templates/{app → blank}/package.json +0 -0
  335. /package/templates/{app → blank}/src/main.ts +0 -0
@@ -0,0 +1,540 @@
1
+ import { ServerResponse } from 'node:http'
2
+ import type { IncomingMessage, OutgoingHttpHeaders } from 'node:http'
3
+ import { Http2ServerRequest, constants as h2constants } from 'node:http2'
4
+ import type { Http2ServerResponse } from 'node:http2'
5
+ import type { Writable } from 'node:stream'
6
+ import type { IncomingMessageWithWrapBodyStream } from './request.ts'
7
+ import {
8
+ abortRequest,
9
+ newRequest,
10
+ recordBodyBufferedBeforeDisconnect,
11
+ Request as LightweightRequest,
12
+ wrapBodyStream,
13
+ toRequestError,
14
+ } from './request.ts'
15
+ import { defaultContentType, cacheKey, Response as LightweightResponse } from './response.ts'
16
+ import type { InternalCache } from './response.ts'
17
+ import type { CustomErrorHandler, FetchCallback, HttpBindings } from './types.ts'
18
+ import {
19
+ readWithoutBlocking,
20
+ writeFromReadableStream,
21
+ writeFromReadableStreamDefaultReader,
22
+ buildOutgoingHttpHeaders,
23
+ } from './utils.ts'
24
+ import { X_ALREADY_SENT } from './utils/response/constants.ts'
25
+
26
+ const outgoingEnded = Symbol('outgoingEnded')
27
+ const incomingDraining = Symbol('incomingDraining')
28
+ type OutgoingHasOutgoingEnded = Http2ServerResponse & {
29
+ [outgoingEnded]?: () => void
30
+ }
31
+ type IncomingHasDrainState = (IncomingMessage | Http2ServerRequest) & {
32
+ [incomingDraining]?: boolean
33
+ }
34
+ type Http1ResponseWithContentLength = ServerResponse & {
35
+ _contentLength: number | null
36
+ _hasBody: boolean
37
+ _removedContLen: boolean
38
+ }
39
+
40
+ const DRAIN_TIMEOUT_MS = 500
41
+ const MAX_DRAIN_BYTES = 64 * 1024 * 1024
42
+
43
+ const drainIncoming = (incoming: IncomingMessage | Http2ServerRequest): void => {
44
+ const incomingWithDrainState = incoming as IncomingHasDrainState
45
+ if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
46
+ return
47
+ }
48
+ incomingWithDrainState[incomingDraining] = true
49
+
50
+ // HTTP/2: streams are multiplexed, so we can close immediately
51
+ // without risking TCP RST racing the response.
52
+ if (incoming instanceof Http2ServerRequest) {
53
+ try {
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ ;(incoming as any).stream?.close?.(h2constants.NGHTTP2_NO_ERROR)
56
+ } catch {
57
+ // stream may already be closed
58
+ }
59
+ return
60
+ }
61
+
62
+ let bytesRead = 0
63
+ const cleanup = () => {
64
+ clearTimeout(timer)
65
+ incoming.off('data', onData)
66
+ incoming.off('end', cleanup)
67
+ incoming.off('error', cleanup)
68
+ }
69
+
70
+ const forceClose = () => {
71
+ cleanup()
72
+ const socket = incoming.socket
73
+ if (socket && !socket.destroyed) {
74
+ if (typeof socket.destroySoon === 'function') {
75
+ socket.destroySoon()
76
+ } else if (typeof socket.destroy === 'function') {
77
+ socket.destroy()
78
+ }
79
+ }
80
+ }
81
+
82
+ const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS)
83
+ timer.unref?.()
84
+
85
+ const onData = (chunk: Buffer) => {
86
+ bytesRead += chunk.length
87
+ if (bytesRead > MAX_DRAIN_BYTES) {
88
+ forceClose()
89
+ }
90
+ }
91
+
92
+ incoming.on('data', onData)
93
+ incoming.on('end', cleanup)
94
+ incoming.on('error', cleanup)
95
+
96
+ incoming.resume()
97
+ }
98
+
99
+ const makeCloseHandler =
100
+ (
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ req: any,
103
+ incoming: IncomingMessage | Http2ServerRequest,
104
+ outgoing: ServerResponse | Http2ServerResponse,
105
+ needsBodyCleanup: boolean
106
+ ): (() => void) =>
107
+ () => {
108
+ if (incoming.errored) {
109
+ recordBodyBufferedBeforeDisconnect(incoming)
110
+ req[abortRequest](incoming.errored.toString())
111
+ } else if (
112
+ !outgoing.writableFinished ||
113
+ // An HTTP/2 response reports writableFinished once its stream is destroyed, including
114
+ // when the client resets the stream mid-response. `aborted` is only set in that case.
115
+ (incoming instanceof Http2ServerRequest && incoming.aborted)
116
+ ) {
117
+ recordBodyBufferedBeforeDisconnect(incoming)
118
+ req[abortRequest]('Client connection prematurely closed.')
119
+ }
120
+
121
+ if (needsBodyCleanup && !incoming.readableEnded) {
122
+ setTimeout(() => {
123
+ if (!incoming.readableEnded) {
124
+ setTimeout(() => {
125
+ drainIncoming(incoming)
126
+ })
127
+ }
128
+ })
129
+ }
130
+ }
131
+
132
+ const isImmediateCacheableResponse = (res: Response): boolean => {
133
+ if (!(cacheKey in res)) {
134
+ return false
135
+ }
136
+
137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ const body = ((res as any)[cacheKey] as InternalCache)[1]
139
+ return body === null || typeof body === 'string' || body instanceof Uint8Array
140
+ }
141
+
142
+ const handleRequestError = (): Response =>
143
+ new Response(null, {
144
+ status: 400,
145
+ })
146
+
147
+ const handleFetchError = (e: unknown): Response =>
148
+ new Response(null, {
149
+ status:
150
+ e instanceof Error && (e.name === 'TimeoutError' || e.constructor.name === 'TimeoutError')
151
+ ? 504 // timeout error emits 504 timeout
152
+ : 500,
153
+ })
154
+
155
+ // `writeHead` takes the same arguments on both response types; their overloads differ only in what they return, so the union is not
156
+ // callable under the current Node types and each call names one of them.
157
+ const handleResponseError = (e: unknown, outgoing: ServerResponse | Http2ServerResponse) => {
158
+ const err = (e instanceof Error ? e : new Error('unknown error', { cause: e })) as Error & {
159
+ code: string
160
+ }
161
+ if (err.code === 'ERR_STREAM_PREMATURE_CLOSE') {
162
+ console.info('The user aborted a request.')
163
+ } else {
164
+ console.error(e)
165
+ if (!outgoing.headersSent) {
166
+ if (outgoing instanceof ServerResponse) {
167
+ // writeHead() may have failed after the fast path set the original body's length.
168
+ ;(outgoing as Http1ResponseWithContentLength)._contentLength = null
169
+ }
170
+ (outgoing as ServerResponse).writeHead(500, { 'Content-Type': 'text/plain' })
171
+ }
172
+ outgoing.end(`Error: ${err.message}`)
173
+ outgoing.destroy(err)
174
+ }
175
+ }
176
+
177
+ const flushHeaders = (outgoing: ServerResponse | Http2ServerResponse) => {
178
+ // If outgoing is ServerResponse (HTTP/1.1), it requires this to flush headers.
179
+ // However, Http2ServerResponse is sent without this.
180
+ if ('flushHeaders' in outgoing && outgoing.writable) {
181
+ outgoing.flushHeaders()
182
+ }
183
+ }
184
+
185
+ // Node's HTTP/1 serializer can add Content-Length without adding a header field.
186
+ // These private fields are covered by compatibility tests in CI. Fall back
187
+ // when automatic insertion would omit the header or preserve a framing header.
188
+ const trySetContentLength = (
189
+ outgoing: ServerResponse | Http2ServerResponse,
190
+ status: number,
191
+ length: number
192
+ ): boolean => {
193
+ const http1 = outgoing as Http1ResponseWithContentLength
194
+ if (
195
+ http1._contentLength === null &&
196
+ http1._hasBody &&
197
+ http1.useChunkedEncodingByDefault &&
198
+ !http1._removedContLen &&
199
+ status >= 200 &&
200
+ status !== 204 &&
201
+ status !== 304 &&
202
+ !outgoing.hasHeader('content-length') &&
203
+ !outgoing.hasHeader('transfer-encoding') &&
204
+ !outgoing.hasHeader('trailer')
205
+ ) {
206
+ http1._contentLength = length
207
+ return true
208
+ }
209
+ return false
210
+ }
211
+
212
+ const writeDefaultHeaders = (
213
+ outgoing: ServerResponse | Http2ServerResponse,
214
+ status: number,
215
+ length: number
216
+ ): void => {
217
+ if (trySetContentLength(outgoing, status, length)) {
218
+ (outgoing as ServerResponse).writeHead(status, { 'Content-Type': defaultContentType })
219
+ } else {
220
+ (outgoing as ServerResponse).writeHead(status, {
221
+ 'Content-Type': defaultContentType,
222
+ 'Content-Length': length,
223
+ })
224
+ }
225
+ }
226
+
227
+ const responseViaCache = async (
228
+ res: Response,
229
+ outgoing: ServerResponse | Http2ServerResponse
230
+ ): Promise<undefined | void> => {
231
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
232
+ let [status, body, header] = (res as any)[cacheKey] as InternalCache
233
+
234
+ // Fast path: no custom headers. Let Node add the length when possible.
235
+ if (!header) {
236
+ if (body === null) {
237
+ (outgoing as ServerResponse).writeHead(status)
238
+ outgoing.end()
239
+ } else if (typeof body === 'string') {
240
+ writeDefaultHeaders(outgoing, status, Buffer.byteLength(body))
241
+ outgoing.end(body)
242
+ } else if (body instanceof Uint8Array) {
243
+ writeDefaultHeaders(outgoing, status, body.byteLength)
244
+ outgoing.end(body)
245
+ } else if (body instanceof Blob) {
246
+ writeDefaultHeaders(outgoing, status, body.size)
247
+ outgoing.end(new Uint8Array(await body.arrayBuffer()))
248
+ } else {
249
+ (outgoing as ServerResponse).writeHead(status, { 'Content-Type': defaultContentType })
250
+ flushHeaders(outgoing)
251
+ await writeFromReadableStream(body, outgoing)?.catch(
252
+ (e) => handleResponseError(e, outgoing) as undefined
253
+ )
254
+ }
255
+ ;(outgoing as OutgoingHasOutgoingEnded)[outgoingEnded]?.()
256
+ return
257
+ }
258
+
259
+ let hasContentLength = false
260
+ let plainHeaders = false
261
+ let canAutoLength = true
262
+ if (header instanceof Headers) {
263
+ hasContentLength = header.has('content-length')
264
+ header = buildOutgoingHttpHeaders(header, body === null ? undefined : defaultContentType)
265
+ } else if (Array.isArray(header)) {
266
+ const headerObj = new Headers(header)
267
+ hasContentLength = headerObj.has('content-length')
268
+ header = buildOutgoingHttpHeaders(headerObj, body === null ? undefined : defaultContentType)
269
+ } else {
270
+ plainHeaders = true
271
+ for (const key in header) {
272
+ if (key.length === 14 && key.toLowerCase() === 'content-length') {
273
+ hasContentLength = true
274
+ break
275
+ }
276
+ if (
277
+ (key.length === 17 && key.toLowerCase() === 'transfer-encoding') ||
278
+ (key.length === 7 && key.toLowerCase() === 'trailer')
279
+ ) {
280
+ canAutoLength = false
281
+ }
282
+ }
283
+ }
284
+
285
+ // in `responseViaCache`, if body is not stream, Transfer-Encoding is considered not chunked
286
+ if (!hasContentLength) {
287
+ let length: number | undefined
288
+ if (typeof body === 'string') {
289
+ length = Buffer.byteLength(body)
290
+ } else if (body instanceof Uint8Array) {
291
+ length = body.byteLength
292
+ } else if (body instanceof Blob) {
293
+ length = body.size
294
+ }
295
+ if (
296
+ length !== undefined &&
297
+ (!plainHeaders || !canAutoLength || !trySetContentLength(outgoing, status, length))
298
+ ) {
299
+ if (plainHeaders) {
300
+ header = { ...header }
301
+ }
302
+ header['Content-Length'] = length
303
+ }
304
+ }
305
+
306
+ (outgoing as ServerResponse).writeHead(status, header)
307
+ if (body == null) {
308
+ outgoing.end()
309
+ } else if (typeof body === 'string' || body instanceof Uint8Array) {
310
+ outgoing.end(body)
311
+ } else if (body instanceof Blob) {
312
+ outgoing.end(new Uint8Array(await body.arrayBuffer()))
313
+ } else {
314
+ flushHeaders(outgoing)
315
+ await writeFromReadableStream(body, outgoing)?.catch(
316
+ (e) => handleResponseError(e, outgoing) as undefined
317
+ )
318
+ }
319
+
320
+ ;(outgoing as OutgoingHasOutgoingEnded)[outgoingEnded]?.()
321
+ }
322
+
323
+ const isPromise = (res: Response | Promise<Response>): res is Promise<Response> =>
324
+ typeof (res as Promise<Response>).then === 'function'
325
+
326
+ const responseViaResponseObject = async (
327
+ res: Response | Promise<Response>,
328
+ outgoing: ServerResponse | Http2ServerResponse,
329
+ options: { errorHandler?: CustomErrorHandler } = {}
330
+ ) => {
331
+ if (isPromise(res)) {
332
+ if (options.errorHandler) {
333
+ try {
334
+ res = await res
335
+ } catch (err) {
336
+ const errRes = await options.errorHandler(err)
337
+ if (!errRes) {
338
+ return
339
+ }
340
+ res = errRes
341
+ }
342
+ } else {
343
+ res = await res.catch(handleFetchError)
344
+ }
345
+ }
346
+
347
+ if (cacheKey in res) {
348
+ return responseViaCache(res as Response, outgoing)
349
+ }
350
+
351
+ const resHeaderRecord: OutgoingHttpHeaders = buildOutgoingHttpHeaders(
352
+ res.headers,
353
+ res.body === null ? undefined : defaultContentType
354
+ )
355
+
356
+ if (res.body) {
357
+ const reader = res.body.getReader()
358
+
359
+ const values: Uint8Array[] = []
360
+ let done = false
361
+ let currentReadPromise: Promise<ReadableStreamReadResult<Uint8Array>> | undefined = undefined
362
+
363
+ if (resHeaderRecord['transfer-encoding'] !== 'chunked') {
364
+ // In the case of synchronous responses, usually a maximum of two (or three in special cases) readings is done
365
+ let maxReadCount = 2
366
+ for (let i = 0; i < maxReadCount; i++) {
367
+ currentReadPromise ||= reader.read()
368
+ const chunk = await readWithoutBlocking(currentReadPromise).catch((e) => {
369
+ console.error(e)
370
+ done = true
371
+ })
372
+ if (!chunk) {
373
+ if (i === 1) {
374
+ // XXX: In Node.js v24, some response bodies are not read all the way through until the next task queue,
375
+ // so wait a moment and retry. (e.g. new Blob([new Uint8Array(contents)]) )
376
+ await new Promise((resolve) => setTimeout(resolve))
377
+ maxReadCount = 3
378
+ continue
379
+ }
380
+
381
+ // Error occurred or currentReadPromise is not yet resolved.
382
+ // If an error occurs, immediately break the loop.
383
+ // If currentReadPromise is not yet resolved, pass it to writeFromReadableStreamDefaultReader.
384
+ break
385
+ }
386
+ currentReadPromise = undefined
387
+
388
+ if (chunk.value) {
389
+ values.push(chunk.value)
390
+ }
391
+ if (chunk.done) {
392
+ done = true
393
+ break
394
+ }
395
+ }
396
+
397
+ if (done && !('content-length' in resHeaderRecord)) {
398
+ resHeaderRecord['content-length'] = values.reduce((acc, value) => acc + value.length, 0)
399
+ }
400
+ }
401
+
402
+ (outgoing as ServerResponse).writeHead(res.status, resHeaderRecord)
403
+ values.forEach((value) => {
404
+ ;(outgoing as Writable).write(value)
405
+ })
406
+ if (done) {
407
+ outgoing.end()
408
+ } else {
409
+ if (values.length === 0) {
410
+ flushHeaders(outgoing)
411
+ }
412
+ await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise)
413
+ }
414
+ } else if (resHeaderRecord[X_ALREADY_SENT]) {
415
+ // do nothing, the response has already been sent
416
+ } else {
417
+ (outgoing as ServerResponse).writeHead(res.status, resHeaderRecord)
418
+ outgoing.end()
419
+ }
420
+
421
+ ;(outgoing as OutgoingHasOutgoingEnded)[outgoingEnded]?.()
422
+ }
423
+
424
+ export const getRequestListener = (
425
+ fetchCallback: FetchCallback,
426
+ options: {
427
+ hostname?: string
428
+ errorHandler?: CustomErrorHandler
429
+ overrideGlobalObjects?: boolean
430
+ autoCleanupIncoming?: boolean
431
+ } = {}
432
+ ) => {
433
+ const autoCleanupIncoming = options.autoCleanupIncoming ?? true
434
+ if (options.overrideGlobalObjects !== false && global.Request !== LightweightRequest) {
435
+ Object.defineProperty(global, 'Request', {
436
+ value: LightweightRequest,
437
+ })
438
+ Object.defineProperty(global, 'Response', {
439
+ value: LightweightResponse,
440
+ })
441
+ }
442
+
443
+ return async (
444
+ incoming: IncomingMessage | Http2ServerRequest,
445
+ outgoing: ServerResponse | Http2ServerResponse
446
+ ) => {
447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
+ let res, req: any
449
+ let needsBodyCleanup = false
450
+ let closeHandlerAttached = false
451
+
452
+ const ensureCloseHandler = () => {
453
+ if (!req || closeHandlerAttached) {
454
+ return
455
+ }
456
+
457
+ closeHandlerAttached = true
458
+ outgoing.on('close', makeCloseHandler(req, incoming, outgoing, needsBodyCleanup))
459
+ }
460
+
461
+ try {
462
+ // `fetchCallback()` requests a Request object, but global.Request is expensive to generate,
463
+ // so generate a pseudo Request object with only the minimum required information.
464
+ req = newRequest(incoming, options.hostname)
465
+
466
+ // For non-GET/HEAD requests, mark for body stream wrapping and H2 cleanup.
467
+ needsBodyCleanup =
468
+ autoCleanupIncoming && !(incoming.method === 'GET' || incoming.method === 'HEAD')
469
+ if (needsBodyCleanup) {
470
+ ;(incoming as IncomingMessageWithWrapBodyStream)[wrapBodyStream] = true
471
+
472
+ if (incoming instanceof Http2ServerRequest) {
473
+ // a Http2ServerResponse instance requires additional processing on exit
474
+ // since outgoing.on('close') is not called even after outgoing.end() is called
475
+ // when the state is incomplete
476
+ ;(outgoing as OutgoingHasOutgoingEnded)[outgoingEnded] = () => {
477
+ // incoming is not consumed to the end
478
+ if (!incoming.readableEnded) {
479
+ setTimeout(() => {
480
+ // in the case of a simple POST request, the cleanup process may be done automatically
481
+ // and readableEnded is true at this point. At that point, nothing is done.
482
+ if (!incoming.readableEnded) {
483
+ setTimeout(() => {
484
+ incoming.destroy()
485
+ // a Http2ServerResponse instance will not terminate without also calling outgoing.destroy()
486
+ outgoing.destroy()
487
+ })
488
+ }
489
+ })
490
+ }
491
+ }
492
+ }
493
+ }
494
+
495
+ res = fetchCallback(req, { incoming, outgoing } as HttpBindings) as
496
+ | Response
497
+ | Promise<Response>
498
+ if (!isPromise(res) && isImmediateCacheableResponse(res)) {
499
+ // Synchronous cacheable response — no close listener needed.
500
+ // No I/O events can fire between fetchCallback returning and responseViaCache
501
+ // completing, so abort detection is not needed here.
502
+ if (needsBodyCleanup && !incoming.readableEnded) {
503
+ // Handler returned without consuming the body; drain after the
504
+ // response is flushed so the socket is freed gracefully (avoids
505
+ // TCP RST racing the response for HTTP/1, and RST_STREAM for HTTP/2).
506
+ outgoing.once('finish', () => {
507
+ if (!incoming.readableEnded) {
508
+ drainIncoming(incoming)
509
+ }
510
+ })
511
+ }
512
+ return responseViaCache(res, outgoing)
513
+ }
514
+ ensureCloseHandler()
515
+ } catch (e: unknown) {
516
+ if (!res) {
517
+ if (options.errorHandler) {
518
+ // Async error handler — register close listener so client disconnect aborts the signal.
519
+ ensureCloseHandler()
520
+ res = await options.errorHandler(req ? e : toRequestError(e))
521
+ if (!res) {
522
+ return
523
+ }
524
+ } else if (!req) {
525
+ res = handleRequestError()
526
+ } else {
527
+ res = handleFetchError(e)
528
+ }
529
+ } else {
530
+ return handleResponseError(e, outgoing)
531
+ }
532
+ }
533
+
534
+ try {
535
+ return await responseViaResponseObject(res, outgoing, options)
536
+ } catch (e) {
537
+ return handleResponseError(e, outgoing)
538
+ }
539
+ }
540
+ }