acrylblends 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/dist/index.d.ts +6 -1
  2. package/dist/index.js +28 -3
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/acryl-inspect/plugin.json +2 -1
  6. package/plugins/acryl-inspect/src/report.ts +16 -13
  7. package/plugins/acryl-inspect/src/service.ts +9 -7
  8. package/plugins/acryl-inspect/tests/report.spec.ts +7 -8
  9. package/plugins/acryl-inspect/tests/service.spec.ts +11 -10
  10. package/plugins/acryl-inspect/upstream.json +2 -2
  11. package/plugins/acryl-node-server/LICENSE +26 -0
  12. package/plugins/acryl-node-server/plugin.json +2 -1
  13. package/plugins/acryl-node-server/src/adapter/conninfo.ts +23 -0
  14. package/plugins/acryl-node-server/src/adapter/early-hints.ts +55 -0
  15. package/plugins/acryl-node-server/src/adapter/error.ts +11 -0
  16. package/plugins/acryl-node-server/src/adapter/headers.ts +249 -0
  17. package/plugins/acryl-node-server/src/adapter/index.ts +6 -0
  18. package/plugins/acryl-node-server/src/adapter/listener.ts +540 -0
  19. package/plugins/acryl-node-server/src/adapter/request.ts +797 -0
  20. package/plugins/acryl-node-server/src/adapter/response.ts +186 -0
  21. package/plugins/acryl-node-server/src/adapter/serve-static.ts +238 -0
  22. package/plugins/acryl-node-server/src/adapter/server.ts +36 -0
  23. package/plugins/acryl-node-server/src/adapter/types.ts +82 -0
  24. package/plugins/acryl-node-server/src/adapter/url.ts +42 -0
  25. package/plugins/acryl-node-server/src/adapter/utils/response/constants.ts +1 -0
  26. package/plugins/acryl-node-server/src/adapter/utils/response.ts +4 -0
  27. package/plugins/acryl-node-server/src/adapter/utils/stream.ts +88 -0
  28. package/plugins/acryl-node-server/src/adapter/utils.ts +96 -0
  29. package/plugins/acryl-node-server/src/adapter/websocket-types.ts +45 -0
  30. package/plugins/acryl-node-server/src/adapter/websocket.ts +375 -0
  31. package/plugins/acryl-node-server/src/index.ts +19 -6
  32. package/plugins/acryl-node-server/tests/adapter/app.ts +76 -0
  33. package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +1 -0
  34. package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
  35. package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +1 -0
  36. package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +1 -0
  37. package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +1 -0
  38. package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +5 -0
  39. package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +1 -0
  40. package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
  41. package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +1 -0
  42. package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +1 -0
  43. package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +1 -0
  44. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +1 -0
  45. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +1 -0
  46. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +1 -0
  47. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +1 -0
  48. package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +1 -0
  49. package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +34 -0
  50. package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +248 -0
  51. package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +457 -0
  52. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +23 -0
  53. package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +27 -0
  54. package/plugins/acryl-node-server/tests/adapter/headers.test.ts +252 -0
  55. package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +190 -0
  56. package/plugins/acryl-node-server/tests/adapter/listener.test.ts +727 -0
  57. package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +189 -0
  58. package/plugins/acryl-node-server/tests/adapter/request.test.ts +1230 -0
  59. package/plugins/acryl-node-server/tests/adapter/response.test.ts +285 -0
  60. package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +849 -0
  61. package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +790 -0
  62. package/plugins/acryl-node-server/tests/adapter/server.test.ts +1302 -0
  63. package/plugins/acryl-node-server/tests/adapter/setup.ts +16 -0
  64. package/plugins/acryl-node-server/tests/adapter/url.test.ts +76 -0
  65. package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +23 -0
  66. package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +75 -0
  67. package/plugins/acryl-node-server/tests/adapter/utils.test.ts +235 -0
  68. package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +260 -0
  69. package/plugins/acryl-node-server/tests/server.spec.ts +44 -8
  70. package/plugins/acryl-node-server/upstream.json +3 -3
  71. package/plugins/acryl-router/LICENSE +26 -0
  72. package/plugins/acryl-router/plugin.json +2 -1
  73. package/plugins/acryl-router/src/client.ts +2 -0
  74. package/plugins/acryl-router/src/connection.ts +42 -0
  75. package/plugins/acryl-router/src/core/app-base.ts +544 -0
  76. package/plugins/acryl-router/src/core/app.test.ts +3833 -0
  77. package/plugins/acryl-router/src/core/app.ts +34 -0
  78. package/plugins/acryl-router/src/core/client/client.test.ts +2313 -0
  79. package/plugins/acryl-router/src/core/client/client.ts +249 -0
  80. package/plugins/acryl-router/src/core/client/fetch-result-please.ts +95 -0
  81. package/plugins/acryl-router/src/core/client/index.ts +17 -0
  82. package/plugins/acryl-router/src/core/client/types.test.ts +149 -0
  83. package/plugins/acryl-router/src/core/client/types.ts +393 -0
  84. package/plugins/acryl-router/src/core/client/utils.test.ts +405 -0
  85. package/plugins/acryl-router/src/core/client/utils.ts +117 -0
  86. package/plugins/acryl-router/src/core/compose.test.ts +751 -0
  87. package/plugins/acryl-router/src/core/compose.ts +73 -0
  88. package/plugins/acryl-router/src/core/context.test.ts +629 -0
  89. package/plugins/acryl-router/src/core/context.ts +781 -0
  90. package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +344 -0
  91. package/plugins/acryl-router/src/core/helper/accepts/accepts.ts +96 -0
  92. package/plugins/acryl-router/src/core/helper/accepts/index.ts +6 -0
  93. package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +55 -0
  94. package/plugins/acryl-router/src/core/helper/adapter/index.ts +90 -0
  95. package/plugins/acryl-router/src/core/helper/conninfo/index.ts +6 -0
  96. package/plugins/acryl-router/src/core/helper/conninfo/types.ts +45 -0
  97. package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +510 -0
  98. package/plugins/acryl-router/src/core/helper/cookie/index.ts +146 -0
  99. package/plugins/acryl-router/src/core/helper/factory/index.test.ts +434 -0
  100. package/plugins/acryl-router/src/core/helper/factory/index.ts +375 -0
  101. package/plugins/acryl-router/src/core/helper/html/index.test.ts +78 -0
  102. package/plugins/acryl-router/src/core/helper/html/index.ts +57 -0
  103. package/plugins/acryl-router/src/core/helper/route/index.test.ts +259 -0
  104. package/plugins/acryl-router/src/core/helper/route/index.ts +144 -0
  105. package/plugins/acryl-router/src/core/helper/streaming/index.ts +9 -0
  106. package/plugins/acryl-router/src/core/helper/streaming/sse.ts +101 -0
  107. package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +128 -0
  108. package/plugins/acryl-router/src/core/helper/streaming/stream.ts +45 -0
  109. package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +34 -0
  110. package/plugins/acryl-router/src/core/helper/streaming/text.ts +15 -0
  111. package/plugins/acryl-router/src/core/helper/streaming/utils.ts +11 -0
  112. package/plugins/acryl-router/src/core/helper/testing/index.test.ts +42 -0
  113. package/plugins/acryl-router/src/core/helper/testing/index.ts +28 -0
  114. package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +124 -0
  115. package/plugins/acryl-router/src/core/helper/websocket/index.ts +140 -0
  116. package/plugins/acryl-router/src/core/http-exception.test.ts +45 -0
  117. package/plugins/acryl-router/src/core/http-exception.ts +77 -0
  118. package/plugins/acryl-router/src/core/index.ts +53 -0
  119. package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +434 -0
  120. package/plugins/acryl-router/src/core/middleware/basic-auth/index.ts +152 -0
  121. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +1018 -0
  122. package/plugins/acryl-router/src/core/middleware/bearer-auth/index.ts +220 -0
  123. package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +273 -0
  124. package/plugins/acryl-router/src/core/middleware/body-limit/index.ts +110 -0
  125. package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +355 -0
  126. package/plugins/acryl-router/src/core/middleware/combine/index.ts +171 -0
  127. package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +535 -0
  128. package/plugins/acryl-router/src/core/middleware/compress/index.ts +142 -0
  129. package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +43 -0
  130. package/plugins/acryl-router/src/core/middleware/context-storage/index.ts +58 -0
  131. package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +532 -0
  132. package/plugins/acryl-router/src/core/middleware/cors/index.ts +163 -0
  133. package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +534 -0
  134. package/plugins/acryl-router/src/core/middleware/csrf/index.ts +150 -0
  135. package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +21 -0
  136. package/plugins/acryl-router/src/core/middleware/etag/digest.ts +95 -0
  137. package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +503 -0
  138. package/plugins/acryl-router/src/core/middleware/etag/index.ts +135 -0
  139. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +217 -0
  140. package/plugins/acryl-router/src/core/middleware/ip-restriction/index.ts +278 -0
  141. package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +1135 -0
  142. package/plugins/acryl-router/src/core/middleware/jwk/index.ts +1 -0
  143. package/plugins/acryl-router/src/core/middleware/jwk/jwk.ts +195 -0
  144. package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +48 -0
  145. package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +802 -0
  146. package/plugins/acryl-router/src/core/middleware/jwt/index.ts +9 -0
  147. package/plugins/acryl-router/src/core/middleware/jwt/jwt.ts +189 -0
  148. package/plugins/acryl-router/src/core/middleware/language/index.test.ts +552 -0
  149. package/plugins/acryl-router/src/core/middleware/language/index.ts +12 -0
  150. package/plugins/acryl-router/src/core/middleware/language/language.ts +314 -0
  151. package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +204 -0
  152. package/plugins/acryl-router/src/core/middleware/logger/index.ts +95 -0
  153. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +292 -0
  154. package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.ts +141 -0
  155. package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +221 -0
  156. package/plugins/acryl-router/src/core/middleware/method-override/index.ts +147 -0
  157. package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +37 -0
  158. package/plugins/acryl-router/src/core/middleware/powered-by/index.ts +35 -0
  159. package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +218 -0
  160. package/plugins/acryl-router/src/core/middleware/pretty-json/index.ts +67 -0
  161. package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +168 -0
  162. package/plugins/acryl-router/src/core/middleware/request-id/index.ts +7 -0
  163. package/plugins/acryl-router/src/core/middleware/request-id/request-id.ts +59 -0
  164. package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +671 -0
  165. package/plugins/acryl-router/src/core/middleware/secure-headers/index.ts +8 -0
  166. package/plugins/acryl-router/src/core/middleware/secure-headers/permissions-policy.ts +101 -0
  167. package/plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts +340 -0
  168. package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +450 -0
  169. package/plugins/acryl-router/src/core/middleware/serve-static/index.ts +135 -0
  170. package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +50 -0
  171. package/plugins/acryl-router/src/core/middleware/serve-static/path.ts +25 -0
  172. package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +70 -0
  173. package/plugins/acryl-router/src/core/middleware/timeout/index.ts +58 -0
  174. package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +310 -0
  175. package/plugins/acryl-router/src/core/middleware/timing/index.ts +8 -0
  176. package/plugins/acryl-router/src/core/middleware/timing/timing.ts +256 -0
  177. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +381 -0
  178. package/plugins/acryl-router/src/core/middleware/trailing-slash/index.ts +156 -0
  179. package/plugins/acryl-router/src/core/request/constants.ts +1 -0
  180. package/plugins/acryl-router/src/core/request.test.ts +751 -0
  181. package/plugins/acryl-router/src/core/request.ts +502 -0
  182. package/plugins/acryl-router/src/core/router/common.case.test.ts +1132 -0
  183. package/plugins/acryl-router/src/core/router/linear-router/index.ts +6 -0
  184. package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +80 -0
  185. package/plugins/acryl-router/src/core/router/linear-router/router.ts +152 -0
  186. package/plugins/acryl-router/src/core/router/pattern-router/index.ts +6 -0
  187. package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +46 -0
  188. package/plugins/acryl-router/src/core/router/pattern-router/router.ts +54 -0
  189. package/plugins/acryl-router/src/core/router/reg-exp-router/index.ts +7 -0
  190. package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.ts +33 -0
  191. package/plugins/acryl-router/src/core/router/reg-exp-router/node.ts +170 -0
  192. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +154 -0
  193. package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.ts +165 -0
  194. package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +265 -0
  195. package/plugins/acryl-router/src/core/router/reg-exp-router/router.ts +174 -0
  196. package/plugins/acryl-router/src/core/router/reg-exp-router/trie.ts +84 -0
  197. package/plugins/acryl-router/src/core/router/smart-router/index.ts +6 -0
  198. package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +13 -0
  199. package/plugins/acryl-router/src/core/router/smart-router/router.ts +70 -0
  200. package/plugins/acryl-router/src/core/router/trie-router/index.ts +6 -0
  201. package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +896 -0
  202. package/plugins/acryl-router/src/core/router/trie-router/node.ts +221 -0
  203. package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +8 -0
  204. package/plugins/acryl-router/src/core/router/trie-router/router.ts +18 -0
  205. package/plugins/acryl-router/src/core/router/utils.ts +1 -0
  206. package/plugins/acryl-router/src/core/router.ts +103 -0
  207. package/plugins/acryl-router/src/core/types.test.ts +4134 -0
  208. package/plugins/acryl-router/src/core/types.ts +2782 -0
  209. package/plugins/acryl-router/src/core/utils/accept.test.ts +299 -0
  210. package/plugins/acryl-router/src/core/utils/accept.ts +268 -0
  211. package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +56 -0
  212. package/plugins/acryl-router/src/core/utils/basic-auth.ts +26 -0
  213. package/plugins/acryl-router/src/core/utils/body.test.ts +496 -0
  214. package/plugins/acryl-router/src/core/utils/body.ts +263 -0
  215. package/plugins/acryl-router/src/core/utils/buffer.test.ts +147 -0
  216. package/plugins/acryl-router/src/core/utils/buffer.ts +117 -0
  217. package/plugins/acryl-router/src/core/utils/color.test.ts +23 -0
  218. package/plugins/acryl-router/src/core/utils/color.ts +56 -0
  219. package/plugins/acryl-router/src/core/utils/compress.ts +10 -0
  220. package/plugins/acryl-router/src/core/utils/concurrent.test.ts +69 -0
  221. package/plugins/acryl-router/src/core/utils/concurrent.ts +55 -0
  222. package/plugins/acryl-router/src/core/utils/constants.ts +4 -0
  223. package/plugins/acryl-router/src/core/utils/cookie.test.ts +460 -0
  224. package/plugins/acryl-router/src/core/utils/cookie.ts +281 -0
  225. package/plugins/acryl-router/src/core/utils/crypto.test.ts +43 -0
  226. package/plugins/acryl-router/src/core/utils/crypto.ts +58 -0
  227. package/plugins/acryl-router/src/core/utils/encode.test.ts +61 -0
  228. package/plugins/acryl-router/src/core/utils/encode.ts +34 -0
  229. package/plugins/acryl-router/src/core/utils/filepath.test.ts +78 -0
  230. package/plugins/acryl-router/src/core/utils/filepath.ts +60 -0
  231. package/plugins/acryl-router/src/core/utils/handler.ts +15 -0
  232. package/plugins/acryl-router/src/core/utils/headers.ts +355 -0
  233. package/plugins/acryl-router/src/core/utils/html.test.ts +16 -0
  234. package/plugins/acryl-router/src/core/utils/html.ts +182 -0
  235. package/plugins/acryl-router/src/core/utils/http-status.ts +72 -0
  236. package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +149 -0
  237. package/plugins/acryl-router/src/core/utils/ipaddr.ts +374 -0
  238. package/plugins/acryl-router/src/core/utils/jwt/index.ts +7 -0
  239. package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +86 -0
  240. package/plugins/acryl-router/src/core/utils/jwt/jwa.ts +38 -0
  241. package/plugins/acryl-router/src/core/utils/jwt/jws.ts +235 -0
  242. package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +1788 -0
  243. package/plugins/acryl-router/src/core/utils/jwt/jwt.ts +292 -0
  244. package/plugins/acryl-router/src/core/utils/jwt/types.ts +157 -0
  245. package/plugins/acryl-router/src/core/utils/jwt/utf8.ts +7 -0
  246. package/plugins/acryl-router/src/core/utils/mime.test.ts +64 -0
  247. package/plugins/acryl-router/src/core/utils/mime.ts +94 -0
  248. package/plugins/acryl-router/src/core/utils/stream.test.ts +212 -0
  249. package/plugins/acryl-router/src/core/utils/stream.ts +107 -0
  250. package/plugins/acryl-router/src/core/utils/types.test.ts +295 -0
  251. package/plugins/acryl-router/src/core/utils/types.ts +123 -0
  252. package/plugins/acryl-router/src/core/utils/url.test.ts +384 -0
  253. package/plugins/acryl-router/src/core/utils/url.ts +337 -0
  254. package/plugins/acryl-router/src/core/validator/index.ts +8 -0
  255. package/plugins/acryl-router/src/core/validator/utils.test.ts +82 -0
  256. package/plugins/acryl-router/src/core/validator/utils.ts +69 -0
  257. package/plugins/acryl-router/src/core/validator/validator.test.ts +1488 -0
  258. package/plugins/acryl-router/src/core/validator/validator.ts +185 -0
  259. package/plugins/acryl-router/src/helpers/index.ts +13 -3
  260. package/plugins/acryl-router/src/helpers/schema-validator.ts +35 -0
  261. package/plugins/acryl-router/src/index.ts +6 -6
  262. package/plugins/acryl-router/src/middleware/index.ts +25 -6
  263. package/plugins/acryl-router/src/middleware/loopback-only.ts +19 -13
  264. package/plugins/acryl-router/src/service.ts +256 -64
  265. package/plugins/acryl-router/tests/docs-examples.spec.ts +152 -0
  266. package/plugins/acryl-router/tests/live-install.spec.ts +2 -2
  267. package/plugins/acryl-router/tests/loader.spec.ts +3 -2
  268. package/plugins/acryl-router/tests/service.spec.ts +264 -66
  269. package/plugins/acryl-router/tests/shadow-state.spec.ts +79 -0
  270. package/plugins/acryl-router/upstream.json +2 -2
  271. package/plugins/acryl-router-http/plugin.json +2 -1
  272. package/plugins/acryl-router-http/src/bridge.ts +3 -1
  273. package/plugins/acryl-router-http/tests/adapter.spec.ts +16 -12
  274. package/plugins/acryl-router-http/tests/surfaces.spec.ts +12 -10
  275. package/plugins/acryl-router-http/upstream.json +3 -3
  276. package/plugins/acryl-state/NOTICE +30 -0
  277. package/plugins/acryl-state/plugin.json +1 -1
  278. package/plugins/acryl-state/src/cell.ts +1 -1
  279. package/plugins/acryl-state/src/service.ts +33 -15
  280. package/plugins/acryl-state/upstream.json +6 -4
  281. package/plugins/builder/script.ts +4 -7
  282. package/plugins/extensions/index.ts +2 -2
  283. package/plugins/extensions/resolve.ts +28 -3
  284. package/plugins/openai/prompt.ts +9 -7
  285. package/plugins/tsconfig.json +5 -4
  286. package/templates/agent/src/routes.ts +37 -27
  287. package/templates/agent/test/model.test.ts +2 -1
  288. package/templates/agent/tsconfig.json +8 -5
  289. package/templates/blank/src/routes.ts +6 -4
  290. package/templates/blank/tsconfig.json +2 -4
  291. package/templates/todo/src/page.ts +1 -1
  292. package/templates/todo/src/todo.ts +56 -29
  293. package/templates/todo/tsconfig.json +2 -4
  294. package/templates/todo/upstream.json +2 -2
  295. package/plugins/acryl-router/src/compose.ts +0 -21
  296. package/plugins/acryl-router/src/context.ts +0 -59
  297. package/plugins/acryl-router/src/helpers/read-body.ts +0 -59
  298. package/plugins/acryl-router/src/helpers/sse.ts +0 -83
  299. package/plugins/acryl-router/src/helpers/validate.ts +0 -44
  300. package/plugins/acryl-router/src/http-error.ts +0 -21
  301. package/plugins/acryl-router/src/middleware/body-limit.ts +0 -25
  302. package/plugins/acryl-router/src/middleware/cors.ts +0 -46
  303. package/plugins/acryl-router/src/middleware/logger.ts +0 -21
  304. package/plugins/acryl-router/src/middleware/request-id.ts +0 -24
  305. package/plugins/acryl-router/src/middleware/secure-headers.ts +0 -23
  306. package/plugins/acryl-router/src/pattern.ts +0 -89
  307. package/plugins/acryl-router/src/registrar.ts +0 -90
  308. package/plugins/acryl-router/src/table.ts +0 -156
  309. package/plugins/acryl-router/src/types.ts +0 -73
  310. package/plugins/acryl-router/src/util.ts +0 -23
  311. package/plugins/acryl-router/tests/api.spec.ts +0 -223
  312. package/plugins/acryl-router/tests/conformance.ts +0 -170
  313. package/plugins/acryl-router/tests/helpers.spec.ts +0 -172
  314. package/plugins/acryl-router/tests/middleware.spec.ts +0 -183
  315. package/plugins/acryl-router/tests/table.spec.ts +0 -47
@@ -0,0 +1,337 @@
1
+ /**
2
+ * @module
3
+ * URL utility.
4
+ */
5
+
6
+ export type Pattern = readonly [string, string, RegExp | true] | '*'
7
+
8
+ export const splitPath = (path: string): string[] => {
9
+ const paths = path.split('/')
10
+ if (paths[0] === '') {
11
+ paths.shift()
12
+ }
13
+ return paths
14
+ }
15
+
16
+ export const splitRoutingPath = (routePath: string): string[] => {
17
+ const { groups, path } = extractGroupsFromPath(routePath)
18
+
19
+ const paths = splitPath(path)
20
+ return replaceGroupMarks(paths, groups)
21
+ }
22
+
23
+ const extractGroupsFromPath = (path: string): { groups: [string, string][]; path: string } => {
24
+ const groups: [string, string][] = []
25
+
26
+ path = path.replace(/\{[^}]+\}/g, (match, index) => {
27
+ const mark = `@${index}`
28
+ groups.push([mark, match])
29
+ return mark
30
+ })
31
+
32
+ return { groups, path }
33
+ }
34
+
35
+ const replaceGroupMarks = (paths: string[], groups: [string, string][]): string[] => {
36
+ for (let i = groups.length - 1; i >= 0; i--) {
37
+ const [mark] = groups[i]
38
+
39
+ for (let j = paths.length - 1; j >= 0; j--) {
40
+ if (paths[j].includes(mark)) {
41
+ paths[j] = paths[j].replace(mark, groups[i][1])
42
+ break
43
+ }
44
+ }
45
+ }
46
+
47
+ return paths
48
+ }
49
+
50
+ const patternCache: { [key: string]: Pattern } = {}
51
+ export const getPattern = (label: string, next?: string): Pattern | null => {
52
+ // * => wildcard
53
+ // :id{[0-9]+} => ([0-9]+)
54
+ // :id => (.+)
55
+
56
+ if (label === '*') {
57
+ return '*'
58
+ }
59
+
60
+ const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/)
61
+ if (match) {
62
+ const cacheKey = `${label}#${next}`
63
+ if (!patternCache[cacheKey]) {
64
+ if (match[2]) {
65
+ patternCache[cacheKey] =
66
+ next && next[0] !== ':' && next[0] !== '*'
67
+ ? [cacheKey, match[1], new RegExp(`^${match[2]}(?=/${next})`)]
68
+ : [label, match[1], new RegExp(`^${match[2]}$`)]
69
+ } else {
70
+ patternCache[cacheKey] = [label, match[1], true]
71
+ }
72
+ }
73
+
74
+ return patternCache[cacheKey]
75
+ }
76
+
77
+ return null
78
+ }
79
+
80
+ type Decoder = (str: string) => string
81
+ export const tryDecode = (str: string, decoder: Decoder): string => {
82
+ try {
83
+ return decoder(str)
84
+ } catch {
85
+ return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
86
+ try {
87
+ return decoder(match)
88
+ } catch {
89
+ return match
90
+ }
91
+ })
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Try to apply decodeURI() to given string.
97
+ * If it fails, skip invalid percent encoding or invalid UTF-8 sequences, and apply decodeURI() to the rest as much as possible.
98
+ * @param str The string to decode.
99
+ * @returns The decoded string that sometimes contains undecodable percent encoding.
100
+ * @example
101
+ * tryDecodeURI('Hello%20World') // 'Hello World'
102
+ * tryDecodeURI('Hello%20World/%A4%A2') // 'Hello World/%A4%A2'
103
+ */
104
+ export const tryDecodeURI = (str: string): string => tryDecode(str, decodeURI)
105
+
106
+ export const getPath = (request: Request): string => {
107
+ const url = request.url
108
+ const start = url.indexOf('/', url.indexOf(':') + 4)
109
+ let i = start
110
+ for (; i < url.length; i++) {
111
+ const charCode = url.charCodeAt(i)
112
+ if (charCode === 37) {
113
+ // '%'
114
+ // If the path contains percent encoding, use `indexOf()` to find '?' or '#' and return the result immediately.
115
+ // Although this is a performance disadvantage, it is acceptable since we prefer cases that do not include percent encoding.
116
+ const queryIndex = url.indexOf('?', i)
117
+ const hashIndex = url.indexOf('#', i)
118
+ const end =
119
+ queryIndex === -1
120
+ ? hashIndex === -1
121
+ ? undefined
122
+ : hashIndex
123
+ : hashIndex === -1
124
+ ? queryIndex
125
+ : Math.min(queryIndex, hashIndex)
126
+ const path = url.slice(start, end)
127
+ return tryDecodeURI(path.includes('%25') ? path.replace(/%25/g, '%2525') : path)
128
+ } else if (charCode === 63 || charCode === 35) {
129
+ // '?' or '#'
130
+ break
131
+ }
132
+ }
133
+ return url.slice(start, i)
134
+ }
135
+
136
+ /**
137
+ * @deprecated
138
+ * Use the `URL` API instead.
139
+ */
140
+ export const getQueryStrings = (url: string): string => {
141
+ const queryIndex = url.indexOf('?', 8)
142
+ if (queryIndex === -1) {
143
+ return ''
144
+ }
145
+
146
+ const hashIndex = url.indexOf('#', 8)
147
+ return hashIndex === -1
148
+ ? url.slice(queryIndex)
149
+ : queryIndex < hashIndex
150
+ ? url.slice(queryIndex, hashIndex)
151
+ : ''
152
+ }
153
+
154
+ export const getPathNoStrict = (request: Request): string => {
155
+ const result = getPath(request)
156
+
157
+ // if strict routing is false => `/hello/hey/` and `/hello/hey` are treated the same
158
+ return result.length > 1 && result.at(-1) === '/' ? result.slice(0, -1) : result
159
+ }
160
+
161
+ /**
162
+ * Merge paths.
163
+ * @param {string[]} ...paths - The paths to merge.
164
+ * @returns {string} The merged path.
165
+ * @example
166
+ * mergePath('/api', '/users') // '/api/users'
167
+ * mergePath('/api/', '/users') // '/api/users'
168
+ * mergePath('/api', '/') // '/api'
169
+ * mergePath('/api/', '/') // '/api/'
170
+ */
171
+ export const mergePath: (...paths: string[]) => string = (
172
+ base: string | undefined,
173
+ sub: string | undefined,
174
+ ...rest: string[]
175
+ ): string => {
176
+ if (rest.length) {
177
+ sub = mergePath(sub as string, ...rest)
178
+ }
179
+ return `${base?.[0] === '/' ? '' : '/'}${base}${
180
+ sub === '/' ? '' : `${base?.at(-1) === '/' ? '' : '/'}${sub?.[0] === '/' ? sub.slice(1) : sub}`
181
+ }`
182
+ }
183
+
184
+ export const checkOptionalParameter = (path: string): string[] | null => {
185
+ /*
186
+ If path is `/api/animals/:type?` it will return:
187
+ [`/api/animals`, `/api/animals/:type`]
188
+ in other cases it will return null
189
+ */
190
+
191
+ if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(':')) {
192
+ return null
193
+ }
194
+
195
+ const segments = path.split('/')
196
+ const results: string[] = []
197
+ let basePath = ''
198
+
199
+ segments.forEach((segment) => {
200
+ if (segment !== '' && !/\:/.test(segment)) {
201
+ basePath += '/' + segment
202
+ } else if (/\:/.test(segment)) {
203
+ if (segment.charCodeAt(segment.length - 1) === 63) {
204
+ if (results.length === 0 && basePath === '') {
205
+ results.push('/')
206
+ } else {
207
+ results.push(basePath)
208
+ }
209
+ const optionalSegment = segment.slice(0, -1)
210
+ basePath += '/' + optionalSegment
211
+ results.push(basePath)
212
+ } else {
213
+ basePath += '/' + segment
214
+ }
215
+ }
216
+ })
217
+
218
+ return results.filter((v, i, a) => a.indexOf(v) === i)
219
+ }
220
+
221
+ export const tryDecodeURIComponent = (str: string): string =>
222
+ str.indexOf('%') !== -1 ? tryDecode(str, decodeURIComponent_) : str
223
+
224
+ // Optimized
225
+ const _decodeURI = (value: string): string => {
226
+ if (value.indexOf('+') !== -1) {
227
+ value = value.replace(/\+/g, ' ')
228
+ }
229
+ return tryDecodeURIComponent(value)
230
+ }
231
+
232
+ const _getQueryParam = (
233
+ url: string,
234
+ key?: string,
235
+ multiple?: boolean
236
+ ): string | undefined | Record<string, string> | string[] | Record<string, string[]> => {
237
+ const hashIndex = url.indexOf('#', 8)
238
+ if (hashIndex !== -1) {
239
+ url = url.slice(0, hashIndex)
240
+ }
241
+
242
+ let encoded
243
+
244
+ if (!multiple && key && key.indexOf('%') === -1 && key.indexOf('+') === -1) {
245
+ // optimized for unencoded key
246
+
247
+ let keyIndex = url.indexOf('?', 8)
248
+ if (keyIndex === -1) {
249
+ return undefined
250
+ }
251
+ if (!url.startsWith(key, keyIndex + 1)) {
252
+ keyIndex = url.indexOf(`&${key}`, keyIndex + 1)
253
+ }
254
+ while (keyIndex !== -1) {
255
+ const trailingKeyCode = url.charCodeAt(keyIndex + key.length + 1)
256
+ if (trailingKeyCode === 61) {
257
+ const valueIndex = keyIndex + key.length + 2
258
+ const endIndex = url.indexOf('&', valueIndex)
259
+ return _decodeURI(url.slice(valueIndex, endIndex === -1 ? undefined : endIndex))
260
+ } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
261
+ return ''
262
+ }
263
+ keyIndex = url.indexOf(`&${key}`, keyIndex + 1)
264
+ }
265
+
266
+ encoded = /[%+]/.test(url)
267
+ if (!encoded) {
268
+ return undefined
269
+ }
270
+ // fallback to default routine
271
+ }
272
+
273
+ const results: Record<string, string> | Record<string, string[]> = Object.create(null)
274
+ encoded ??= /[%+]/.test(url)
275
+
276
+ let keyIndex = url.indexOf('?', 8)
277
+ while (keyIndex !== -1) {
278
+ const nextKeyIndex = url.indexOf('&', keyIndex + 1)
279
+ let valueIndex = url.indexOf('=', keyIndex)
280
+ if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
281
+ valueIndex = -1
282
+ }
283
+ let name = url.slice(
284
+ keyIndex + 1,
285
+ valueIndex === -1 ? (nextKeyIndex === -1 ? undefined : nextKeyIndex) : valueIndex
286
+ )
287
+ if (encoded) {
288
+ name = _decodeURI(name)
289
+ }
290
+
291
+ keyIndex = nextKeyIndex
292
+
293
+ if (name === '') {
294
+ continue
295
+ }
296
+
297
+ let value
298
+ if (valueIndex === -1) {
299
+ value = ''
300
+ } else {
301
+ value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? undefined : nextKeyIndex)
302
+ if (encoded) {
303
+ value = _decodeURI(value)
304
+ }
305
+ }
306
+
307
+ if (multiple) {
308
+ if (!(results[name] && Array.isArray(results[name]))) {
309
+ results[name] = []
310
+ }
311
+ ;(results[name] as string[]).push(value)
312
+ } else {
313
+ results[name] ??= value
314
+ }
315
+ }
316
+
317
+ return key ? results[key] : results
318
+ }
319
+
320
+ export const getQueryParam: (
321
+ url: string,
322
+ key?: string
323
+ ) => string | undefined | Record<string, string> = _getQueryParam as (
324
+ url: string,
325
+ key?: string
326
+ ) => string | undefined | Record<string, string>
327
+
328
+ export const getQueryParams = (
329
+ url: string,
330
+ key?: string
331
+ ): string[] | undefined | Record<string, string[]> => {
332
+ return _getQueryParam(url, key, true) as string[] | undefined | Record<string, string[]>
333
+ }
334
+
335
+ // `decodeURIComponent` is a long name.
336
+ // By making it a function, we can use it commonly when minified, reducing the amount of code.
337
+ export const decodeURIComponent_ = decodeURIComponent
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module
3
+ * Validator for App.
4
+ */
5
+
6
+ export { validator } from './validator.ts'
7
+ export type { ValidationFunction } from './validator.ts'
8
+ export type { InferInput } from './utils.ts'
@@ -0,0 +1,82 @@
1
+ import { expectTypeOf } from 'vitest'
2
+ import type { InferInput, IsLiteralUnion } from './utils.ts'
3
+
4
+ describe('IsLiteralUnion', () => {
5
+ it('should return true for literal union types', () => {
6
+ expectTypeOf<IsLiteralUnion<'asc' | 'desc', string>>().toEqualTypeOf<true>()
7
+ })
8
+
9
+ it('should return false for single literal', () => {
10
+ expectTypeOf<IsLiteralUnion<'asc', string>>().toEqualTypeOf<false>()
11
+ })
12
+
13
+ it('should return false for wide string type', () => {
14
+ expectTypeOf<IsLiteralUnion<string, string>>().toEqualTypeOf<false>()
15
+ })
16
+
17
+ it('should return true for literal union with undefined', () => {
18
+ expectTypeOf<IsLiteralUnion<'asc' | 'desc' | undefined, string>>().toEqualTypeOf<true>()
19
+ })
20
+ })
21
+
22
+ describe('InferInput', () => {
23
+ it('should preserve literal union types for query', () => {
24
+ expectTypeOf<InferInput<{ orderBy: 'asc' | 'desc' }, 'query'>>().toEqualTypeOf<{
25
+ orderBy: 'asc' | 'desc'
26
+ }>()
27
+ })
28
+
29
+ it('should convert string to string | string[] for query', () => {
30
+ expectTypeOf<InferInput<{ page: string }, 'query'>>().toEqualTypeOf<{
31
+ page: string | string[]
32
+ }>()
33
+ })
34
+
35
+ it('should convert number to string | string[] for query', () => {
36
+ expectTypeOf<InferInput<{ page: number }, 'query'>>().toEqualTypeOf<{
37
+ page: string | string[]
38
+ }>()
39
+ })
40
+
41
+ it('should preserve optional union (T | undefined) for query', () => {
42
+ expectTypeOf<InferInput<{ name?: string | undefined }, 'query'>>().toEqualTypeOf<{
43
+ name?: string | undefined
44
+ }>()
45
+ })
46
+
47
+ it('should preserve literal union with undefined for query', () => {
48
+ expectTypeOf<InferInput<{ orderBy?: 'asc' | 'desc' | undefined }, 'query'>>().toEqualTypeOf<{
49
+ orderBy?: 'asc' | 'desc' | undefined
50
+ }>()
51
+ })
52
+
53
+ it('should convert unknown to string | string[] for query (coerce support)', () => {
54
+ expectTypeOf<InferInput<{ page: unknown }, 'query'>>().toEqualTypeOf<{
55
+ page: string | string[]
56
+ }>()
57
+ })
58
+
59
+ it('should handle object | undefined for query (optional schema)', () => {
60
+ expectTypeOf<InferInput<{ name?: string | undefined } | undefined, 'query'>>().toEqualTypeOf<
61
+ { name?: string | undefined } | undefined
62
+ >()
63
+ })
64
+
65
+ it('should convert string to string for param', () => {
66
+ expectTypeOf<InferInput<{ id: string }, 'param'>>().toEqualTypeOf<{
67
+ id: string
68
+ }>()
69
+ })
70
+
71
+ it('should convert string to string for header', () => {
72
+ expectTypeOf<InferInput<{ authorization: string }, 'header'>>().toEqualTypeOf<{
73
+ authorization: string
74
+ }>()
75
+ })
76
+
77
+ it('should convert string to string for cookie', () => {
78
+ expectTypeOf<InferInput<{ session: string }, 'cookie'>>().toEqualTypeOf<{
79
+ session: string
80
+ }>()
81
+ })
82
+ })
@@ -0,0 +1,69 @@
1
+ import type { FormValue, ParsedFormValue, ValidationTargets } from '../types.ts'
2
+ import type { UnionToIntersection } from '../utils/types.ts'
3
+
4
+ /**
5
+ * Checks if T is a literal union type (e.g., 'asc' | 'desc')
6
+ * that should be preserved in input types.
7
+ * Returns true for union literals, false for single literals or wide types.
8
+ */
9
+ export type IsLiteralUnion<T, Base> = [Exclude<T, undefined>] extends [Base]
10
+ ? [Exclude<T, undefined>] extends [UnionToIntersection<Exclude<T, undefined>>]
11
+ ? false
12
+ : true
13
+ : false
14
+
15
+ // Check if type is an optional union (T | undefined) but not unknown/any
16
+ type IsOptionalUnion<T> = [unknown] extends [T]
17
+ ? false // unknown or any
18
+ : undefined extends T
19
+ ? true
20
+ : false
21
+
22
+ // Helper to force TypeScript to expand type aliases
23
+ type SimplifyDeep<T> = { [K in keyof T]: T[K] } & {}
24
+
25
+ type InferInputInner<
26
+ Output,
27
+ Target extends keyof ValidationTargets,
28
+ T extends FormValue,
29
+ > = SimplifyDeep<{
30
+ [K in keyof Output]: IsLiteralUnion<Output[K], string> extends true
31
+ ? Output[K]
32
+ : IsOptionalUnion<Output[K]> extends true
33
+ ? Output[K]
34
+ : Target extends 'form'
35
+ ? T | T[]
36
+ : Target extends 'query'
37
+ ? string | string[]
38
+ : Target extends 'param'
39
+ ? string
40
+ : Target extends 'header'
41
+ ? string
42
+ : Target extends 'cookie'
43
+ ? string
44
+ : unknown
45
+ }>
46
+
47
+ /**
48
+ * Utility type to infer input types for validation targets.
49
+ * Preserves literal union types (e.g., 'asc' | 'desc') while using
50
+ * the default ValidationTargets type for other values.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * // In @acryl-router/zod-validator or similar:
55
+ * type Input = InferInput<z.input<Schema>, 'query'>
56
+ * // { orderBy: 'asc' | 'desc', page: string | string[] }
57
+ * ```
58
+ */
59
+ export type InferInput<
60
+ Output,
61
+ Target extends keyof ValidationTargets,
62
+ T extends FormValue = ParsedFormValue,
63
+ > = [Exclude<Output, undefined>] extends [never]
64
+ ? {}
65
+ : [Exclude<Output, undefined>] extends [object]
66
+ ? undefined extends Output
67
+ ? SimplifyDeep<InferInputInner<Exclude<Output, undefined>, Target, T>> | undefined
68
+ : SimplifyDeep<InferInputInner<Output, Target, T>>
69
+ : {}