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,496 @@
1
+ import { parseBody } from './body.ts'
2
+ import type { BodyData } from './body.ts'
3
+
4
+ type RecursiveRecord<K extends string, T> = {
5
+ [key in K]: T | RecursiveRecord<K, T>
6
+ }
7
+
8
+ describe('Parse Body Util', () => {
9
+ const FORM_URL = 'https://localhost/form'
10
+ const SEARCH_URL = 'https://localhost/search'
11
+
12
+ const createRequest = (
13
+ url: string,
14
+ method: 'POST',
15
+ body: BodyInit,
16
+ headers?: { [key: string]: string }
17
+ ) => {
18
+ return new Request(url, {
19
+ method,
20
+ body,
21
+ headers,
22
+ })
23
+ }
24
+
25
+ const createNestedKey = (depth: number) =>
26
+ Array(depth + 1)
27
+ .fill('a')
28
+ .join('.')
29
+
30
+ it('should parse `multipart/form-data`', async () => {
31
+ const data = new FormData()
32
+ data.append('message', 'hello')
33
+
34
+ const req = createRequest(FORM_URL, 'POST', data)
35
+
36
+ expect(await parseBody(req)).toEqual({ message: 'hello' })
37
+ })
38
+
39
+ it('should parse `x-www-form-urlencoded`', async () => {
40
+ const searchParams = new URLSearchParams()
41
+ searchParams.append('message', 'hello')
42
+
43
+ const req = createRequest(SEARCH_URL, 'POST', searchParams, {
44
+ 'Content-Type': 'application/x-www-form-urlencoded',
45
+ })
46
+
47
+ expect(await parseBody(req)).toEqual({ message: 'hello' })
48
+ })
49
+
50
+ it('should parse mixed-case `x-www-form-urlencoded`', async () => {
51
+ const searchParams = new URLSearchParams()
52
+ searchParams.append('message', 'hello')
53
+
54
+ const req = createRequest(SEARCH_URL, 'POST', searchParams, {
55
+ 'Content-Type': 'Application/X-WWW-Form-Urlencoded',
56
+ })
57
+
58
+ expect(await parseBody(req)).toEqual({ message: 'hello' })
59
+ })
60
+
61
+ it('should parse mixed-case `multipart/form-data`', async () => {
62
+ const data = new FormData()
63
+ data.append('message', 'hello')
64
+
65
+ const source = createRequest(FORM_URL, 'POST', data)
66
+ const contentType = source.headers
67
+ .get('Content-Type')!
68
+ .replace('multipart/form-data', 'Multipart/Form-Data')
69
+ const req = createRequest(FORM_URL, 'POST', await source.arrayBuffer(), {
70
+ 'Content-Type': contentType,
71
+ })
72
+
73
+ expect(await parseBody(req)).toEqual({ message: 'hello' })
74
+ })
75
+
76
+ it('should not parse multiple values in default', async () => {
77
+ const data = new FormData()
78
+ data.append('file', 'bbb')
79
+ data.append('message', 'hello')
80
+
81
+ const req = createRequest(FORM_URL, 'POST', data)
82
+
83
+ expect(await parseBody(req)).toEqual({
84
+ file: 'bbb',
85
+ message: 'hello',
86
+ })
87
+ })
88
+
89
+ it('should not update file object properties', async () => {
90
+ const file = new File(['foo'], 'file1', {
91
+ type: 'application/octet-stream',
92
+ })
93
+ const data = new FormData()
94
+ data.append('file', file)
95
+ data.append('file.hoo', 'hoo')
96
+
97
+ const req = createRequest(FORM_URL, 'POST', data)
98
+
99
+ const parsedData = await parseBody(req, { dot: true })
100
+ expect(parsedData.file).not.instanceOf(File)
101
+ expect(parsedData).toEqual({
102
+ file: {
103
+ hoo: 'hoo',
104
+ },
105
+ })
106
+ })
107
+
108
+ it('should override value if `all` option is false', async () => {
109
+ const data = new FormData()
110
+ data.append('file', 'aaa')
111
+ data.append('file', 'bbb')
112
+ data.append('message', 'hello')
113
+
114
+ const req = createRequest(FORM_URL, 'POST', data)
115
+
116
+ expect(await parseBody(req)).toEqual({
117
+ file: 'bbb',
118
+ message: 'hello',
119
+ })
120
+ })
121
+
122
+ it('should parse multiple values if `all` option is true', async () => {
123
+ const data = new FormData()
124
+ data.append('file', 'aaa')
125
+ data.append('file', 'bbb')
126
+ data.append('message', 'hello')
127
+
128
+ const req = createRequest(FORM_URL, 'POST', data)
129
+
130
+ expect(await parseBody(req, { all: true })).toEqual({
131
+ file: ['aaa', 'bbb'],
132
+ message: 'hello',
133
+ })
134
+ })
135
+
136
+ it('should not parse nested values in default', async () => {
137
+ const data = new FormData()
138
+ data.append('obj.key1', 'value1')
139
+ data.append('obj.key2', 'value2')
140
+
141
+ const req = createRequest(FORM_URL, 'POST', data)
142
+
143
+ expect(await parseBody(req, { dot: false })).toEqual({
144
+ 'obj.key1': 'value1',
145
+ 'obj.key2': 'value2',
146
+ })
147
+ })
148
+
149
+ it('should not parse nested values in default for non-nested keys', async () => {
150
+ const data = new FormData()
151
+ data.append('key1', 'value1')
152
+ data.append('key2', 'value2')
153
+
154
+ const req = createRequest(FORM_URL, 'POST', data)
155
+
156
+ expect(await parseBody(req, { dot: false })).toEqual({
157
+ key1: 'value1',
158
+ key2: 'value2',
159
+ })
160
+ })
161
+
162
+ it('should handle nested values and non-nested values together with dot option true', async () => {
163
+ const data = new FormData()
164
+ data.append('obj.key1', 'value1')
165
+ data.append('obj.key2', 'value2')
166
+ data.append('key3', 'value3')
167
+
168
+ const req = createRequest(FORM_URL, 'POST', data)
169
+
170
+ expect(await parseBody(req, { dot: true })).toEqual({
171
+ obj: { key1: 'value1', key2: 'value2' },
172
+ key3: 'value3',
173
+ })
174
+ })
175
+
176
+ it('should handle deeply nested objects with dot option true', async () => {
177
+ const data = new FormData()
178
+ data.append('a.b.c.d', 'value')
179
+
180
+ const req = createRequest(FORM_URL, 'POST', data)
181
+
182
+ expect(await parseBody(req, { dot: true })).toEqual({
183
+ a: { b: { c: { d: 'value' } } },
184
+ })
185
+ })
186
+
187
+ it('should allow 32 nesting levels by default', async () => {
188
+ const data = new FormData()
189
+ data.append(createNestedKey(32), 'value')
190
+
191
+ const req = createRequest(FORM_URL, 'POST', data)
192
+ let nested: unknown = await parseBody(req, { dot: true })
193
+
194
+ for (let i = 0; i <= 32; i++) {
195
+ nested = (nested as Record<string, unknown>).a
196
+ }
197
+ expect(nested).toBe('value')
198
+ })
199
+
200
+ it('should reject dot notation deeper than the default limit', async () => {
201
+ const data = new FormData()
202
+ data.append(createNestedKey(33), 'value')
203
+
204
+ const req = createRequest(FORM_URL, 'POST', data)
205
+
206
+ await expect(parseBody(req, { dot: true })).rejects.toThrow('Nesting limit exceeded')
207
+ })
208
+
209
+ it('should reject deeply nested keys without splitting every segment', async () => {
210
+ const req = createRequest(SEARCH_URL, 'POST', `${'.'.repeat(65_530)}=value`, {
211
+ 'Content-Type': 'application/x-www-form-urlencoded',
212
+ })
213
+
214
+ await expect(parseBody(req, { dot: true })).rejects.toThrow('Nesting limit exceeded')
215
+ })
216
+
217
+ it('should reject too many nested objects across multiple fields', async () => {
218
+ const searchParams = new URLSearchParams()
219
+ for (let i = 0; i <= 10_000; i++) {
220
+ searchParams.append(`field${i}.value`, 'value')
221
+ }
222
+
223
+ const req = createRequest(SEARCH_URL, 'POST', searchParams, {
224
+ 'Content-Type': 'application/x-www-form-urlencoded',
225
+ })
226
+
227
+ await expect(parseBody(req, { dot: true })).rejects.toThrow('Nesting limit exceeded')
228
+ })
229
+
230
+ it('should skip keys starting with __proto__. to prevent prototype pollution', async () => {
231
+ const data = new FormData()
232
+ data.append('__proto__.polluted', 'malicious')
233
+
234
+ const req = createRequest(FORM_URL, 'POST', data)
235
+
236
+ expect(await parseBody(req, { dot: true })).toEqual({})
237
+ })
238
+
239
+ it('should skip keys containing nested __proto__. to prevent prototype pollution', async () => {
240
+ const data = new FormData()
241
+ data.append('a.__proto__.polluted', 'malicious')
242
+
243
+ const req = createRequest(FORM_URL, 'POST', data)
244
+
245
+ expect(await parseBody(req, { dot: true })).toEqual({})
246
+ })
247
+
248
+ it('should not pollute Object.prototype via __proto__ keys', async () => {
249
+ const data = new FormData()
250
+ data.append('__proto__.injected', 'yes')
251
+ data.append('a.__proto__.injected', 'yes')
252
+
253
+ const req = createRequest(FORM_URL, 'POST', data)
254
+
255
+ await parseBody(req, { dot: true })
256
+
257
+ expect(({} as Record<string, unknown>).injected).toBeUndefined()
258
+ })
259
+
260
+ it('should parse key ending with __proto__ as a normal value', async () => {
261
+ const data = new FormData()
262
+ data.append('a.__proto__', 'value')
263
+
264
+ const req = createRequest(FORM_URL, 'POST', data)
265
+
266
+ const result = await parseBody(req, { dot: true })
267
+ expect(result).toHaveProperty('a')
268
+ expect(
269
+ Object.getOwnPropertyDescriptor(
270
+ (result as Record<string, Record<string, string>>).a,
271
+ '__proto__'
272
+ )?.value
273
+ ).toBe('value')
274
+ })
275
+
276
+ it('should parse key containing __proto__ as a substring normally', async () => {
277
+ const data = new FormData()
278
+ data.append('data__proto__key.value', 'test')
279
+
280
+ const req = createRequest(FORM_URL, 'POST', data)
281
+
282
+ expect(await parseBody(req, { dot: true })).toEqual({
283
+ data__proto__key: { value: 'test' },
284
+ })
285
+ })
286
+
287
+ it('should parse nested values if `dot` option is true', async () => {
288
+ const data = new FormData()
289
+ data.append('obj.key1', 'value1')
290
+ data.append('obj.key2', 'value2')
291
+
292
+ const req = createRequest(FORM_URL, 'POST', data)
293
+
294
+ expect(await parseBody(req, { dot: true })).toEqual({
295
+ obj: { key1: 'value1', key2: 'value2' },
296
+ })
297
+ })
298
+
299
+ it('should parse data if both `all` and `dot` are set', async () => {
300
+ const data = new FormData()
301
+ data.append('obj.sub.foo', 'value1')
302
+ data.append('obj.sub.foo', 'value2')
303
+ data.append('key', 'value3')
304
+
305
+ const req = createRequest(FORM_URL, 'POST', data)
306
+
307
+ expect(await parseBody(req, { dot: true, all: true })).toEqual({
308
+ obj: { sub: { foo: ['value1', 'value2'] } },
309
+ key: 'value3',
310
+ })
311
+ })
312
+
313
+ it('should parse nested values if values are `File`', async () => {
314
+ const file1 = new File(['foo'], 'file1', {
315
+ type: 'application/octet-stream',
316
+ })
317
+ const file2 = new File(['bar'], 'file2', {
318
+ type: 'application/octet-stream',
319
+ })
320
+ const data = new FormData()
321
+ data.append('file.file1', file1)
322
+ data.append('file.file2', file2)
323
+
324
+ const req = createRequest(FORM_URL, 'POST', data)
325
+
326
+ const result = await parseBody(req, { all: true, dot: true })
327
+ expect(result).toMatchObject({
328
+ file: {
329
+ file1: { name: 'file1', type: 'application/octet-stream' },
330
+ file2: { name: 'file2', type: 'application/octet-stream' },
331
+ },
332
+ })
333
+ })
334
+
335
+ it('should parse multiple values if values are `File`', async () => {
336
+ const file1 = new File(['foo'], 'file1', {
337
+ type: 'application/octet-stream',
338
+ })
339
+ const file2 = new File(['bar'], 'file2', {
340
+ type: 'application/octet-stream',
341
+ })
342
+ const data = new FormData()
343
+ data.append('file', file1)
344
+ data.append('file', file2)
345
+
346
+ const req = createRequest(FORM_URL, 'POST', data)
347
+
348
+ const result = await parseBody(req, { all: true })
349
+ expect(result).toMatchObject({
350
+ file: [
351
+ { name: 'file1', type: 'application/octet-stream' },
352
+ { name: 'file2', type: 'application/octet-stream' },
353
+ ],
354
+ })
355
+ })
356
+
357
+ it('should parse multiple values if key ends with `[]`', async () => {
358
+ const data = new FormData()
359
+ data.append('file[]', 'aaa')
360
+ data.append('file[]', 'bbb')
361
+ data.append('message', 'hello')
362
+
363
+ const req = createRequest(FORM_URL, 'POST', data)
364
+
365
+ expect(await parseBody(req, { all: true })).toEqual({
366
+ 'file[]': ['aaa', 'bbb'],
367
+ message: 'hello',
368
+ })
369
+ })
370
+
371
+ it('should parse single value as array if the key has `[]`', async () => {
372
+ const data = new FormData()
373
+ data.append('foo[]', 'bar')
374
+ const req = createRequest(FORM_URL, 'POST', data)
375
+
376
+ expect(await parseBody(req, { all: true })).toEqual({
377
+ 'foo[]': ['bar'],
378
+ })
379
+ })
380
+
381
+ it('should return blank object if body is JSON', async () => {
382
+ const payload = { message: 'hello acryl' }
383
+
384
+ const req = createRequest('http://localhost/json', 'POST', JSON.stringify(payload), {
385
+ 'Content-Type': 'application/json',
386
+ })
387
+
388
+ expect(await parseBody(req)).toEqual({})
389
+ })
390
+
391
+ describe('Return type', () => {
392
+ let req: Request
393
+ beforeEach(() => {
394
+ req = createRequest(FORM_URL, 'POST', new FormData())
395
+ })
396
+
397
+ it('without options', async () => {
398
+ expectTypeOf((await parseBody(req))['key']).toEqualTypeOf<string | File>()
399
+ })
400
+
401
+ it('{all: true}', async () => {
402
+ expectTypeOf((await parseBody(req, { all: true }))['key']).toEqualTypeOf<
403
+ string | File | (string | File)[]
404
+ >()
405
+ })
406
+
407
+ it('{all: boolean}', async () => {
408
+ expectTypeOf((await parseBody(req, { all: !!Math.random() }))['key']).toEqualTypeOf<
409
+ string | File | (string | File)[]
410
+ >()
411
+ })
412
+
413
+ it('{dot: true}', async () => {
414
+ expectTypeOf((await parseBody(req, { dot: true }))['key']).toEqualTypeOf<
415
+ string | File | RecursiveRecord<string, string | File>
416
+ >()
417
+ })
418
+
419
+ it('{dot: boolean}', async () => {
420
+ expectTypeOf((await parseBody(req, { dot: !!Math.random() }))['key']).toEqualTypeOf<
421
+ string | File | RecursiveRecord<string, string | File>
422
+ >()
423
+ })
424
+
425
+ it('{all: true, dot: true}', async () => {
426
+ expectTypeOf((await parseBody(req, { all: true, dot: true }))['key']).toEqualTypeOf<
427
+ | string
428
+ | File
429
+ | (string | File)[]
430
+ | RecursiveRecord<string, string | File | (string | File)[]>
431
+ >()
432
+ })
433
+
434
+ it('{all: boolean, dot: boolean}', async () => {
435
+ expectTypeOf(
436
+ (await parseBody(req, { all: !!Math.random(), dot: !!Math.random() }))['key']
437
+ ).toEqualTypeOf<
438
+ | string
439
+ | File
440
+ | (string | File)[]
441
+ | RecursiveRecord<string, string | File | (string | File)[]>
442
+ >()
443
+ })
444
+
445
+ it('specify return type explicitly', async () => {
446
+ expectTypeOf(
447
+ await parseBody<{ key1: string; key2: string }>(req, {
448
+ all: !!Math.random(),
449
+ dot: !!Math.random(),
450
+ })
451
+ ).toEqualTypeOf<{ key1: string; key2: string }>()
452
+ })
453
+ })
454
+ })
455
+
456
+ describe('BodyData', () => {
457
+ it('without options', async () => {
458
+ expectTypeOf(({} as BodyData)['key']).toEqualTypeOf<string | File>()
459
+ })
460
+
461
+ it('{all: true}', async () => {
462
+ expectTypeOf(({} as BodyData<{ all: true }>)['key']).toEqualTypeOf<
463
+ string | File | (string | File)[]
464
+ >()
465
+ })
466
+
467
+ it('{all: boolean}', async () => {
468
+ expectTypeOf(({} as BodyData<{ all: boolean }>)['key']).toEqualTypeOf<
469
+ string | File | (string | File)[]
470
+ >()
471
+ })
472
+
473
+ it('{dot: true}', async () => {
474
+ expectTypeOf(({} as BodyData<{ dot: true }>)['key']).toEqualTypeOf<
475
+ string | File | RecursiveRecord<string, string | File>
476
+ >()
477
+ })
478
+
479
+ it('{dot: boolean}', async () => {
480
+ expectTypeOf(({} as BodyData<{ dot: boolean }>)['key']).toEqualTypeOf<
481
+ string | File | RecursiveRecord<string, string | File>
482
+ >()
483
+ })
484
+
485
+ it('{all: true, dot: true}', async () => {
486
+ expectTypeOf(({} as BodyData<{ all: true; dot: true }>)['key']).toEqualTypeOf<
487
+ string | File | (string | File)[] | RecursiveRecord<string, string | File | (string | File)[]>
488
+ >()
489
+ })
490
+
491
+ it('{all: boolean, dot: boolean}', async () => {
492
+ expectTypeOf(({} as BodyData<{ all: boolean; dot: boolean }>)['key']).toEqualTypeOf<
493
+ string | File | (string | File)[] | RecursiveRecord<string, string | File | (string | File)[]>
494
+ >()
495
+ })
496
+ })