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,149 @@
1
+ import {
2
+ convertIPv4BinaryToString,
3
+ convertIPv4ToBinary,
4
+ convertIPv6BinaryToString,
5
+ convertIPv6ToBinary,
6
+ distinctRemoteAddr,
7
+ expandIPv6,
8
+ INVALID_IP_ADDRESS_ERROR_CODE,
9
+ } from './ipaddr.ts'
10
+
11
+ const expectInvalidIPAddressError = (fn: () => unknown) => {
12
+ try {
13
+ fn()
14
+ } catch (error) {
15
+ expect(error).toBeInstanceOf(TypeError)
16
+ expect(error).toHaveProperty('code', INVALID_IP_ADDRESS_ERROR_CODE)
17
+ return
18
+ }
19
+ throw new Error('Expected invalid IP address error')
20
+ }
21
+
22
+ describe('expandIPv6', () => {
23
+ it('Should result be valid', () => {
24
+ expect(expandIPv6('1::1')).toBe('0001:0000:0000:0000:0000:0000:0000:0001')
25
+ expect(expandIPv6('::1')).toBe('0000:0000:0000:0000:0000:0000:0000:0001')
26
+ expect(expandIPv6('2001:2::')).toBe('2001:0002:0000:0000:0000:0000:0000:0000')
27
+ expect(expandIPv6('2001:2::')).toBe('2001:0002:0000:0000:0000:0000:0000:0000')
28
+ expect(expandIPv6('2001:0:0:db8::1')).toBe('2001:0000:0000:0db8:0000:0000:0000:0001')
29
+ expect(expandIPv6('::ffff:127.0.0.1')).toBe('0000:0000:0000:0000:0000:ffff:7f00:0001')
30
+ expect(expandIPv6('::ffff:0.0.0.1')).toBe('0000:0000:0000:0000:0000:ffff:0000:0001')
31
+ expect(expandIPv6('2001:db8:1:2:3:4:0.0.0.1')).toBe('2001:0db8:0001:0002:0003:0004:0000:0001')
32
+ expect(expandIPv6('::0.0.0.0')).toBe('0000:0000:0000:0000:0000:0000:0000:0000')
33
+ })
34
+
35
+ it('Should expand the unspecified address "::" to eight zero groups', () => {
36
+ expect(expandIPv6('::')).toBe('0000:0000:0000:0000:0000:0000:0000:0000')
37
+ })
38
+ })
39
+ describe('distinctRemoteAddr', () => {
40
+ it('Should result be valid', () => {
41
+ expect(distinctRemoteAddr('1::1')).toBe('IPv6')
42
+ expect(distinctRemoteAddr('::1')).toBe('IPv6')
43
+ expect(distinctRemoteAddr('::ffff:127.0.0.1')).toBe('IPv6')
44
+
45
+ expect(distinctRemoteAddr('192.168.2.0')).toBe('IPv4')
46
+ expect(distinctRemoteAddr('192.168.2.0')).toBe('IPv4')
47
+
48
+ expect(distinctRemoteAddr('example.com')).toBeUndefined()
49
+ })
50
+
51
+ it('Should reject invalid IPv4 addresses with octets > 255', () => {
52
+ expect(distinctRemoteAddr('1.2.3.256')).toBeUndefined()
53
+ expect(distinctRemoteAddr('1.2.3.999')).toBeUndefined()
54
+ expect(distinctRemoteAddr('1.2.2.355')).toBeUndefined()
55
+ expect(distinctRemoteAddr('256.0.0.1')).toBeUndefined()
56
+ expect(distinctRemoteAddr('999.999.999.999')).toBeUndefined()
57
+ })
58
+
59
+ it('Should accept valid IPv4 edge cases', () => {
60
+ expect(distinctRemoteAddr('0.0.0.0')).toBe('IPv4')
61
+ expect(distinctRemoteAddr('255.255.255.255')).toBe('IPv4')
62
+ expect(distinctRemoteAddr('1.2.3.4')).toBe('IPv4')
63
+ })
64
+ })
65
+
66
+ describe('convertIPv4ToBinary', () => {
67
+ it('Should result is valid', () => {
68
+ expect(convertIPv4ToBinary('0.0.0.0')).toBe(0n)
69
+ expect(convertIPv4ToBinary('0.0.0.1')).toBe(1n)
70
+
71
+ expect(convertIPv4ToBinary('0.0.1.0')).toBe(1n << 8n)
72
+ })
73
+
74
+ test.each(['1.2.3.256', '1.2.3', '1.2.3.4.5', '1..3.4', '01.2.3.4', 'a.b.c.d'])(
75
+ 'Should throw for invalid IPv4: %s',
76
+ (input) => {
77
+ expectInvalidIPAddressError(() => convertIPv4ToBinary(input))
78
+ }
79
+ )
80
+ })
81
+
82
+ describe('convertIPv4ToString', () => {
83
+ // add tons of test cases here
84
+ test.each`
85
+ input | expected
86
+ ${'0.0.0.0'} | ${'0.0.0.0'}
87
+ ${'0.0.0.1'} | ${'0.0.0.1'}
88
+ ${'0.0.1.0'} | ${'0.0.1.0'}
89
+ `('convertIPv4ToString($input) === $expected', ({ input, expected }) => {
90
+ expect(convertIPv4BinaryToString(convertIPv4ToBinary(input))).toBe(expected)
91
+ })
92
+ })
93
+
94
+ describe('convertIPv6ToBinary', () => {
95
+ it('Should result is valid', () => {
96
+ expect(convertIPv6ToBinary('::0')).toBe(0n)
97
+ expect(convertIPv6ToBinary('::1')).toBe(1n)
98
+
99
+ expect(convertIPv6ToBinary('::f')).toBe(15n)
100
+ expect(convertIPv6ToBinary('1234::5678')).toBe(24196103360772296748952112894165669496n)
101
+ expect(convertIPv6ToBinary('::ffff:127.0.0.1')).toBe(281472812449793n)
102
+ expect(convertIPv6ToBinary('fe80::1%eth0')).toBe(convertIPv6ToBinary('fe80::1'))
103
+ })
104
+
105
+ test.each([
106
+ '1::2::3',
107
+ '1:2:3:4:5:6:7:8:9',
108
+ '1:2:3:4:5:6:7',
109
+ '12345::',
110
+ 'gggg::',
111
+ '::ffff:127.0.0.256',
112
+ '1234:::5678',
113
+ '2001:db8::1%eth0',
114
+ '::ffff:127.0.0.1%eth0',
115
+ '1:2:3%eth0',
116
+ 'gggg%eth0',
117
+ 'fe80::1%',
118
+ ])('Should throw for invalid IPv6: %s', (input) => {
119
+ expectInvalidIPAddressError(() => convertIPv6ToBinary(input))
120
+ })
121
+ })
122
+
123
+ describe('convertIPv6ToString', () => {
124
+ // add tons of test cases here
125
+ test.each`
126
+ input | expected
127
+ ${'::1'} | ${'::1'}
128
+ ${'1::'} | ${'1::'}
129
+ ${'1234::5678'} | ${'1234::5678'}
130
+ ${'2001:2::'} | ${'2001:2::'}
131
+ ${'2001::db8:0:0:0:0:1'} | ${'2001:0:db8::1'}
132
+ ${'1234:5678:9abc:def0:1234:5678:9abc:def0'} | ${'1234:5678:9abc:def0:1234:5678:9abc:def0'}
133
+ ${'::ffff:127.0.0.1'} | ${'::ffff:127.0.0.1'}
134
+ ${'fe80::1%eth0'} | ${'fe80::1'}
135
+ ${'1:0:2:3:4:5:6:7'} | ${'1:0:2:3:4:5:6:7'}
136
+ ${'0:1:2:3:4:5:6:7'} | ${'0:1:2:3:4:5:6:7'}
137
+ ${'1:2:3:4:5:6:7:0'} | ${'1:2:3:4:5:6:7:0'}
138
+ ${'1:0:0:2:3:4:5:6'} | ${'1::2:3:4:5:6'}
139
+ `('convertIPv6ToString($input) === $expected', ({ input, expected }) => {
140
+ expect(convertIPv6BinaryToString(convertIPv6ToBinary(input))).toBe(expected)
141
+ })
142
+
143
+ it('Should compress the unspecified address (all zero groups) to "::"', () => {
144
+ expect(convertIPv6BinaryToString(0n)).toBe('::')
145
+ expect(convertIPv6BinaryToString(convertIPv6ToBinary('::'))).toBe('::')
146
+ // The output must round-trip back to the same binary value.
147
+ expect(convertIPv6ToBinary(convertIPv6BinaryToString(0n))).toBe(0n)
148
+ })
149
+ })
@@ -0,0 +1,374 @@
1
+ /**
2
+ * Utils for IP Addresses
3
+ * @module
4
+ */
5
+
6
+ import type { AddressType } from '../helper/conninfo/index.ts'
7
+
8
+ /**
9
+ * Expand IPv6 Address
10
+ * @param ipV6 Shorten IPv6 Address
11
+ * @return expanded IPv6 Address
12
+ */
13
+ export const expandIPv6 = (ipV6: string): string => {
14
+ const sections = ipV6.split(':')
15
+ const lastSection = sections.at(-1) as string
16
+ if (IPV4_REGEX.test(lastSection)) {
17
+ const octets = lastSection.split('.').map(Number)
18
+ sections.splice(
19
+ -1,
20
+ 1,
21
+ ((octets[0] << 8) | octets[1]).toString(16),
22
+ ((octets[2] << 8) | octets[3]).toString(16)
23
+ )
24
+ }
25
+ for (let i = 0; i < sections.length; i++) {
26
+ const node = sections[i]
27
+ if (node !== '') {
28
+ sections[i] = node.padStart(4, '0')
29
+ } else {
30
+ // Keep a single empty slot for `::` zero expansion.
31
+ while (sections[i + 1] === '') {
32
+ sections.splice(i + 1, 1)
33
+ }
34
+ sections[i] = new Array(8 - sections.length + 1).fill('0000').join(':')
35
+ }
36
+ }
37
+ return sections.join(':')
38
+ }
39
+
40
+ const IPV4_OCTET_PART = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])'
41
+ const IPV4_REGEX = new RegExp(`^(?:${IPV4_OCTET_PART}\\.){3}${IPV4_OCTET_PART}$`)
42
+ export const INVALID_IP_ADDRESS_ERROR_CODE = 'ERR_INVALID_IP_ADDRESS'
43
+ export type InvalidIPAddressError = TypeError & {
44
+ code: typeof INVALID_IP_ADDRESS_ERROR_CODE
45
+ }
46
+ const CHAR_CODE_0 = 48
47
+ const CHAR_CODE_9 = 57
48
+ const CHAR_CODE_A = 65
49
+ const CHAR_CODE_F = 70
50
+ const CHAR_CODE_a = 97
51
+ const CHAR_CODE_f = 102
52
+ const CHAR_CODE_DOT = 46
53
+ const CHAR_CODE_COLON = 58
54
+ const CHAR_CODE_PERCENT = 37
55
+
56
+ /**
57
+ * Distinct Remote Addr
58
+ * @param remoteAddr Remote Addr
59
+ */
60
+ export const distinctRemoteAddr = (remoteAddr: string): AddressType => {
61
+ if (IPV4_REGEX.test(remoteAddr)) {
62
+ return 'IPv4'
63
+ }
64
+ if (remoteAddr.includes(':')) {
65
+ // Domain can't include `:`
66
+ return 'IPv6'
67
+ }
68
+ }
69
+
70
+ const createInvalidIPAddressError = (message: string): InvalidIPAddressError => {
71
+ const error = new TypeError(message) as InvalidIPAddressError
72
+ error.code = INVALID_IP_ADDRESS_ERROR_CODE
73
+ return error
74
+ }
75
+
76
+ const throwInvalidIPv4Address = (ipv4: string): never => {
77
+ throw createInvalidIPAddressError(`Invalid IPv4 address: ${ipv4}`)
78
+ }
79
+
80
+ const throwInvalidIPv6Address = (ipv6: string): never => {
81
+ throw createInvalidIPAddressError(`Invalid IPv6 address: ${ipv6}`)
82
+ }
83
+
84
+ const parseIPv4ToBinary = (
85
+ ipv4: string,
86
+ start: number,
87
+ end: number,
88
+ onInvalid: () => never
89
+ ): bigint => {
90
+ let result = 0n
91
+ let octets = 0
92
+ let octet = 0
93
+ let digits = 0
94
+ let firstDigit = 0
95
+
96
+ for (let i = start; i <= end; i++) {
97
+ const code = i < end ? ipv4.charCodeAt(i) : CHAR_CODE_DOT
98
+ if (code >= CHAR_CODE_0 && code <= CHAR_CODE_9) {
99
+ if (digits === 0) {
100
+ firstDigit = code
101
+ } else if (firstDigit === CHAR_CODE_0) {
102
+ onInvalid()
103
+ }
104
+ octet = octet * 10 + code - CHAR_CODE_0
105
+ if (octet > 255) {
106
+ onInvalid()
107
+ }
108
+ digits++
109
+ continue
110
+ }
111
+
112
+ if (code !== CHAR_CODE_DOT || digits === 0 || octets === 4) {
113
+ onInvalid()
114
+ }
115
+
116
+ result = (result << 8n) + BigInt(octet)
117
+ octets++
118
+ octet = 0
119
+ digits = 0
120
+ }
121
+
122
+ if (octets !== 4) {
123
+ onInvalid()
124
+ }
125
+
126
+ return result
127
+ }
128
+
129
+ const parseIPv6HexCode = (code: number): number => {
130
+ if (code >= CHAR_CODE_0 && code <= CHAR_CODE_9) {
131
+ return code - CHAR_CODE_0
132
+ }
133
+ if (code >= CHAR_CODE_A && code <= CHAR_CODE_F) {
134
+ return code - CHAR_CODE_A + 10
135
+ }
136
+ if (code >= CHAR_CODE_a && code <= CHAR_CODE_f) {
137
+ return code - CHAR_CODE_a + 10
138
+ }
139
+ return -1
140
+ }
141
+
142
+ const isIPv6LinkLocal = (ipv6binary: bigint): boolean => ipv6binary >> 118n === 0x3fan
143
+
144
+ /**
145
+ * Convert IPv4 to Uint8Array
146
+ * @param ipv4 IPv4 Address
147
+ * @returns BigInt
148
+ */
149
+ export const convertIPv4ToBinary = (ipv4: string): bigint => {
150
+ return parseIPv4ToBinary(ipv4, 0, ipv4.length, () => throwInvalidIPv4Address(ipv4))
151
+ }
152
+
153
+ /**
154
+ * Convert IPv6 to Uint8Array
155
+ * @param ipv6 IPv6 Address
156
+ * @returns BigInt
157
+ */
158
+ export const convertIPv6ToBinary = (ipv6: string): bigint => {
159
+ const length = ipv6.length
160
+ const sections: number[] = []
161
+ let hasZoneId = false
162
+ let compressAt = -1
163
+ let index = 0
164
+
165
+ if (length === 0) {
166
+ throwInvalidIPv6Address(ipv6)
167
+ }
168
+
169
+ while (index < length) {
170
+ if (sections.length > 8) {
171
+ throwInvalidIPv6Address(ipv6)
172
+ }
173
+
174
+ let code = ipv6.charCodeAt(index)
175
+
176
+ if (code === CHAR_CODE_PERCENT) {
177
+ if (index + 1 === length) {
178
+ throwInvalidIPv6Address(ipv6)
179
+ }
180
+ hasZoneId = true
181
+ break
182
+ }
183
+
184
+ if (code === CHAR_CODE_COLON) {
185
+ if (index + 1 < length && ipv6.charCodeAt(index + 1) === CHAR_CODE_COLON) {
186
+ if (compressAt !== -1) {
187
+ throwInvalidIPv6Address(ipv6)
188
+ }
189
+ compressAt = sections.length
190
+ index += 2
191
+ continue
192
+ }
193
+ throwInvalidIPv6Address(ipv6)
194
+ }
195
+
196
+ let value = 0
197
+ let digits = 0
198
+ const sectionStart = index
199
+
200
+ while (index < length) {
201
+ code = ipv6.charCodeAt(index)
202
+ const hex = parseIPv6HexCode(code)
203
+ if (hex === -1) {
204
+ break
205
+ }
206
+ if (digits === 4) {
207
+ throwInvalidIPv6Address(ipv6)
208
+ }
209
+ value = (value << 4) | hex
210
+ digits++
211
+ index++
212
+ }
213
+
214
+ if (index < length && ipv6.charCodeAt(index) === CHAR_CODE_DOT) {
215
+ let ipv4End = length
216
+ for (let i = index; i < length; i++) {
217
+ if (ipv6.charCodeAt(i) === CHAR_CODE_PERCENT) {
218
+ if (i + 1 === length) {
219
+ throwInvalidIPv6Address(ipv6)
220
+ }
221
+ hasZoneId = true
222
+ ipv4End = i
223
+ break
224
+ }
225
+ }
226
+ const ipv4 = parseIPv4ToBinary(ipv6, sectionStart, ipv4End, () =>
227
+ throwInvalidIPv6Address(ipv6)
228
+ )
229
+ sections.push(Number((ipv4 >> 16n) & 0xffffn), Number(ipv4 & 0xffffn))
230
+ index = length
231
+ break
232
+ }
233
+
234
+ if (digits === 0) {
235
+ throwInvalidIPv6Address(ipv6)
236
+ }
237
+
238
+ sections.push(value)
239
+
240
+ if (index === length) {
241
+ break
242
+ }
243
+
244
+ code = ipv6.charCodeAt(index)
245
+ if (code === CHAR_CODE_PERCENT) {
246
+ if (index + 1 === length) {
247
+ throwInvalidIPv6Address(ipv6)
248
+ }
249
+ hasZoneId = true
250
+ break
251
+ }
252
+
253
+ if (code !== CHAR_CODE_COLON) {
254
+ throwInvalidIPv6Address(ipv6)
255
+ }
256
+
257
+ if (index + 1 < length && ipv6.charCodeAt(index + 1) === CHAR_CODE_COLON) {
258
+ if (compressAt !== -1) {
259
+ throwInvalidIPv6Address(ipv6)
260
+ }
261
+ compressAt = sections.length
262
+ index += 2
263
+ continue
264
+ }
265
+
266
+ index++
267
+ if (index === length) {
268
+ throwInvalidIPv6Address(ipv6)
269
+ }
270
+ }
271
+
272
+ if (compressAt === -1 ? sections.length !== 8 : sections.length >= 8) {
273
+ throwInvalidIPv6Address(ipv6)
274
+ }
275
+
276
+ let result = 0n
277
+ const zeros = compressAt === -1 ? 0 : 8 - sections.length
278
+ const firstSectionEnd = compressAt === -1 ? sections.length : compressAt
279
+ for (let i = 0; i < firstSectionEnd; i++) {
280
+ result <<= 16n
281
+ result += BigInt(sections[i])
282
+ }
283
+ for (let i = 0; i < zeros; i++) {
284
+ result <<= 16n
285
+ }
286
+ for (let i = firstSectionEnd; i < sections.length; i++) {
287
+ result <<= 16n
288
+ result += BigInt(sections[i])
289
+ }
290
+ if (hasZoneId && !isIPv6LinkLocal(result)) {
291
+ throwInvalidIPv6Address(ipv6)
292
+ }
293
+ return result
294
+ }
295
+
296
+ /**
297
+ * Convert a binary representation of an IPv4 address to a string.
298
+ * @param ipV4 binary IPv4 Address
299
+ * @return IPv4 Address in string
300
+ */
301
+ export const convertIPv4BinaryToString = (ipV4: bigint): string => {
302
+ const sections = []
303
+ for (let i = 0; i < 4; i++) {
304
+ sections.push((ipV4 >> BigInt(8 * (3 - i))) & 0xffn)
305
+ }
306
+ return sections.join('.')
307
+ }
308
+
309
+ /**
310
+ * Check if a binary IPv6 address is an IPv4-mapped IPv6 address (::ffff:x.x.x.x)
311
+ * @param ipv6binary binary IPv6 Address
312
+ * @return true if the address is an IPv4-mapped IPv6 address
313
+ */
314
+ export const isIPv4MappedIPv6 = (ipv6binary: bigint): boolean => ipv6binary >> 32n === 0xffffn
315
+
316
+ /**
317
+ * Extract the IPv4 portion from an IPv4-mapped IPv6 address
318
+ * @param ipv6binary binary IPv4-mapped IPv6 Address
319
+ * @return binary IPv4 Address
320
+ */
321
+ export const convertIPv4MappedIPv6ToIPv4 = (ipv6binary: bigint): bigint => ipv6binary & 0xffffffffn
322
+
323
+ /**
324
+ * Convert a binary representation of an IPv6 address to a string.
325
+ * @param ipV6 binary IPv6 Address
326
+ * @return normalized IPv6 Address in string
327
+ */
328
+ export const convertIPv6BinaryToString = (ipV6: bigint): string => {
329
+ if (ipV6 === 0n) {
330
+ // The unspecified address compresses every group, which the generic
331
+ // logic below would render as a single ":". Handle it explicitly.
332
+ return '::'
333
+ }
334
+
335
+ if (isIPv4MappedIPv6(ipV6)) {
336
+ return `::ffff:${convertIPv4BinaryToString(convertIPv4MappedIPv6ToIPv4(ipV6))}`
337
+ }
338
+
339
+ const sections = []
340
+ for (let i = 0; i < 8; i++) {
341
+ sections.push(((ipV6 >> BigInt(16 * (7 - i))) & 0xffffn).toString(16))
342
+ }
343
+
344
+ let currentZeroStart = -1
345
+ let maxZeroStart = -1
346
+ let maxZeroEnd = -1
347
+ for (let i = 0; i < 8; i++) {
348
+ if (sections[i] === '0') {
349
+ if (currentZeroStart === -1) {
350
+ currentZeroStart = i
351
+ }
352
+ } else {
353
+ if (currentZeroStart > -1) {
354
+ if (i - currentZeroStart > maxZeroEnd - maxZeroStart) {
355
+ maxZeroStart = currentZeroStart
356
+ maxZeroEnd = i
357
+ }
358
+ currentZeroStart = -1
359
+ }
360
+ }
361
+ }
362
+ if (currentZeroStart > -1) {
363
+ if (8 - currentZeroStart > maxZeroEnd - maxZeroStart) {
364
+ maxZeroStart = currentZeroStart
365
+ maxZeroEnd = 8
366
+ }
367
+ }
368
+ // RFC 5952 4.2.2: compress only zero runs of at least two 16-bit fields.
369
+ if (maxZeroStart !== -1 && maxZeroEnd - maxZeroStart > 1) {
370
+ sections.splice(maxZeroStart, maxZeroEnd - maxZeroStart, ':')
371
+ }
372
+
373
+ return sections.join(':').replace(/:{2,}/g, '::')
374
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module
3
+ * JWT utility.
4
+ */
5
+
6
+ import { decode, sign, verify, verifyWithJwks } from './jwt.ts'
7
+ export const Jwt = { sign, verify, decode, verifyWithJwks }
@@ -0,0 +1,86 @@
1
+ import { AlgorithmTypes } from './jwa.ts'
2
+ import type { AsymmetricAlgorithm, SymmetricAlgorithm, SignatureAlgorithm } from './jwa.ts'
3
+
4
+ describe('Types', () => {
5
+ it('AlgorithmTypes', () => {
6
+ expect('HS256' as AlgorithmTypes).toBe(AlgorithmTypes.HS256)
7
+ expect('HS384' as AlgorithmTypes).toBe(AlgorithmTypes.HS384)
8
+ expect('HS512' as AlgorithmTypes).toBe(AlgorithmTypes.HS512)
9
+ expect('RS256' as AlgorithmTypes).toBe(AlgorithmTypes.RS256)
10
+ expect('RS384' as AlgorithmTypes).toBe(AlgorithmTypes.RS384)
11
+ expect('RS512' as AlgorithmTypes).toBe(AlgorithmTypes.RS512)
12
+ expect('PS256' as AlgorithmTypes).toBe(AlgorithmTypes.PS256)
13
+ expect('PS384' as AlgorithmTypes).toBe(AlgorithmTypes.PS384)
14
+ expect('PS512' as AlgorithmTypes).toBe(AlgorithmTypes.PS512)
15
+ expect('ES256' as AlgorithmTypes).toBe(AlgorithmTypes.ES256)
16
+ expect('ES384' as AlgorithmTypes).toBe(AlgorithmTypes.ES384)
17
+ expect('ES512' as AlgorithmTypes).toBe(AlgorithmTypes.ES512)
18
+ expect('EdDSA' as AlgorithmTypes).toBe(AlgorithmTypes.EdDSA)
19
+
20
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
21
+ // @ts-ignore
22
+ expect(undefined as AlgorithmTypes).toBe(undefined)
23
+ expect('' as AlgorithmTypes).toBe('')
24
+ })
25
+
26
+ it('SymmetricAlgorithm type should only include HMAC algorithms', () => {
27
+ // These should be valid SymmetricAlgorithm values
28
+ const hs256: SymmetricAlgorithm = 'HS256'
29
+ const hs384: SymmetricAlgorithm = 'HS384'
30
+ const hs512: SymmetricAlgorithm = 'HS512'
31
+
32
+ expect(hs256).toBe('HS256')
33
+ expect(hs384).toBe('HS384')
34
+ expect(hs512).toBe('HS512')
35
+
36
+ // Type-level test: these would cause compile errors if uncommented
37
+ // const rs256: SymmetricAlgorithm = 'RS256' // Error: Type '"RS256"' is not assignable to type 'SymmetricAlgorithm'
38
+ })
39
+
40
+ it('AsymmetricAlgorithm type should only include asymmetric algorithms', () => {
41
+ // These should be valid AsymmetricAlgorithm values
42
+ const asymmetricAlgs: AsymmetricAlgorithm[] = [
43
+ 'RS256',
44
+ 'RS384',
45
+ 'RS512',
46
+ 'PS256',
47
+ 'PS384',
48
+ 'PS512',
49
+ 'ES256',
50
+ 'ES384',
51
+ 'ES512',
52
+ 'EdDSA',
53
+ ]
54
+
55
+ expect(asymmetricAlgs).toHaveLength(10)
56
+
57
+ // Verify all asymmetric algorithms are included
58
+ expect(asymmetricAlgs).toContain('RS256')
59
+ expect(asymmetricAlgs).toContain('ES256')
60
+ expect(asymmetricAlgs).toContain('EdDSA')
61
+
62
+ // Type-level test: these would cause compile errors if uncommented
63
+ // const hs256: AsymmetricAlgorithm = 'HS256' // Error: Type '"HS256"' is not assignable to type 'AsymmetricAlgorithm'
64
+ })
65
+
66
+ it('SignatureAlgorithm type should include all algorithms', () => {
67
+ // SignatureAlgorithm should include both symmetric and asymmetric algorithms
68
+ const allAlgs: SignatureAlgorithm[] = [
69
+ 'HS256',
70
+ 'HS384',
71
+ 'HS512',
72
+ 'RS256',
73
+ 'RS384',
74
+ 'RS512',
75
+ 'PS256',
76
+ 'PS384',
77
+ 'PS512',
78
+ 'ES256',
79
+ 'ES384',
80
+ 'ES512',
81
+ 'EdDSA',
82
+ ]
83
+
84
+ expect(allAlgs).toHaveLength(13)
85
+ })
86
+ })
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @module
3
+ * JSON Web Algorithms (JWA)
4
+ * https://datatracker.ietf.org/doc/html/rfc7518
5
+ */
6
+
7
+ export const AlgorithmTypes = {
8
+ HS256: 'HS256',
9
+ HS384: 'HS384',
10
+ HS512: 'HS512',
11
+ RS256: 'RS256',
12
+ RS384: 'RS384',
13
+ RS512: 'RS512',
14
+ PS256: 'PS256',
15
+ PS384: 'PS384',
16
+ PS512: 'PS512',
17
+ ES256: 'ES256',
18
+ ES384: 'ES384',
19
+ ES512: 'ES512',
20
+ EdDSA: 'EdDSA',
21
+ } as const
22
+ export type AlgorithmTypes = (typeof AlgorithmTypes)[keyof typeof AlgorithmTypes]
23
+
24
+ export type SignatureAlgorithm = keyof typeof AlgorithmTypes
25
+
26
+ export type SymmetricAlgorithm = 'HS256' | 'HS384' | 'HS512'
27
+
28
+ export type AsymmetricAlgorithm =
29
+ | 'RS256'
30
+ | 'RS384'
31
+ | 'RS512'
32
+ | 'PS256'
33
+ | 'PS384'
34
+ | 'PS512'
35
+ | 'ES256'
36
+ | 'ES384'
37
+ | 'ES512'
38
+ | 'EdDSA'