acrylblends 1.0.3 → 1.0.5

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 (256) hide show
  1. package/docs/framework/agents/index.md +6 -4
  2. package/docs/framework/workshop/README.md +3 -3
  3. package/docs/framework/workshop/facilitator.md +1 -0
  4. package/lib/accept-CNNHu4Cf.js +193 -0
  5. package/lib/{accepts-XBuZPVRI.js → accepts-Btq83xPd.js} +1 -1
  6. package/lib/accepts.js +1 -1
  7. package/lib/acryl-base.js +1 -331
  8. package/lib/adapter-CaZ6FZUU.js +37 -0
  9. package/lib/adapter.js +1 -36
  10. package/lib/{app-BM0rTCp7.js → app-CQcGWjrk.js} +4 -4
  11. package/lib/app-base-CpRMZL4v.js +332 -0
  12. package/lib/{audit-BXnYsLge.d.ts → audit-D5z9uwOP.d.ts} +14 -1
  13. package/lib/{base-NSN_SNv-.js → base-D_6kfOr-.js} +1 -1
  14. package/lib/basic-auth-C0HTRpXh.js +20 -0
  15. package/lib/basic-auth-DFLflXNe.js +95 -0
  16. package/lib/basic-auth.js +1 -94
  17. package/lib/bearer-auth-Cwxt-vgS.js +94 -0
  18. package/lib/bearer-auth.js +1 -93
  19. package/lib/body-D7f4e7w_.js +94 -0
  20. package/lib/body-limit-WmIjWRLt.js +66 -0
  21. package/lib/body-limit.js +1 -65
  22. package/lib/buffer-CkEOJCcY.js +51 -0
  23. package/lib/bun.js +3 -3
  24. package/lib/cache-B0bHH7s5.js +169 -0
  25. package/lib/cache.js +1 -168
  26. package/lib/{client-DDLXwhBo.js → client-BrMFnMEd.js} +1 -1
  27. package/lib/{client-modules-CLvWOjbd.js → client-modules-drj4mjhj.js} +4 -4
  28. package/lib/client.js +1 -1
  29. package/lib/color-COa3DplO.js +37 -0
  30. package/lib/combine-TWuGdcbC.js +137 -0
  31. package/lib/combine.js +1 -136
  32. package/lib/{components-cEW3ovK0.js → components-B2ka9Ax1.js} +4 -4
  33. package/lib/{components-JXVm45kK.js → components-PVXwaOaC.js} +2 -2
  34. package/lib/compress-BzWqsHF1.js +79 -0
  35. package/lib/compress-C-9vK4B2.d.ts +11 -0
  36. package/lib/compress-DCyrrQ5D.js +11 -0
  37. package/lib/compress.d.ts +1 -1
  38. package/lib/compress.js +2 -78
  39. package/lib/concurrent-DrF3d2c-.js +30 -0
  40. package/lib/conninfo-BCROmdnf.d.ts +11 -0
  41. package/lib/conninfo-CWJwieh4.js +19 -0
  42. package/lib/constants-CBSEudrb.js +7 -0
  43. package/lib/{context-DDO0cfuP.js → context-CkOh7Ygv.js} +2 -2
  44. package/lib/context-storage-iuPoI_CR.js +52 -0
  45. package/lib/context-storage.js +1 -51
  46. package/lib/cookie-B1LlkzOe.js +125 -0
  47. package/lib/cookie-BHIduy2T.js +82 -0
  48. package/lib/cookie.js +1 -81
  49. package/lib/cordis/db-sqlite.d.ts +1 -1
  50. package/lib/cordis/door.d.ts +17 -3
  51. package/lib/cordis/door.js +123 -16
  52. package/lib/cordis/inspect.js +4 -4
  53. package/lib/cordis/kv-db.d.ts +1 -1
  54. package/lib/cordis/kv-db.js +1 -1
  55. package/lib/cordis/kv-json.d.ts +1 -1
  56. package/lib/cordis/kv-json.js +1 -1
  57. package/lib/cordis/node-server.d.ts +1 -1
  58. package/lib/cordis/node-server.js +3 -116
  59. package/lib/cordis/router-http.d.ts +1 -1
  60. package/lib/cordis/router-http.js +2 -2
  61. package/lib/cordis/router.d.ts +1 -1
  62. package/lib/cordis/router.js +4 -4
  63. package/lib/cordis/state.js +7 -7
  64. package/lib/{core-CaY8XDZ6.js → core-BOu1jYua.js} +1 -1
  65. package/lib/cors-CbAQ-8qU.js +106 -0
  66. package/lib/cors.js +1 -105
  67. package/lib/crypto-iVP-N-tS.js +34 -0
  68. package/lib/csrf-DqqOZtgy.js +101 -0
  69. package/lib/csrf.js +1 -100
  70. package/lib/css-C5CPVMvM.js +134 -0
  71. package/lib/css.js +2 -133
  72. package/lib/db/sqlite.d.ts +1 -25
  73. package/lib/dev-CLgu-JRe.js +50 -0
  74. package/lib/dev.js +1 -49
  75. package/lib/dom-YjND9Jt3.js +74 -0
  76. package/lib/door/host.d.ts +2 -2
  77. package/lib/door/host.js +1 -1
  78. package/lib/door/page.d.ts +12 -1
  79. package/lib/door/page.js +22 -1
  80. package/lib/door/protocol.d.ts +2 -2
  81. package/lib/door/protocol.js +2 -197
  82. package/lib/encode-BhbNLrjp.js +33 -0
  83. package/lib/factory-CLdSf-xS.js +30 -0
  84. package/lib/factory.js +1 -29
  85. package/lib/handler-C0wZ0KwO.js +12 -0
  86. package/lib/helpers-BEjcdbgw.js +5 -0
  87. package/lib/{hooks-w72iLeFR.js → hooks-CfC07ri0.js} +1 -1
  88. package/lib/html-CgNa89xw.js +31 -0
  89. package/lib/html-DGExBFNg.js +103 -0
  90. package/lib/html.d.ts +2 -5
  91. package/lib/html.js +2 -30
  92. package/lib/http-exception-MjWkT89V.js +54 -0
  93. package/lib/http-exception.js +1 -53
  94. package/lib/{index-D4nVR3wu.d.ts → index-DMOtA-NJ.d.ts} +7 -1
  95. package/lib/index-dAzQsJG9.d.ts +6 -0
  96. package/lib/index.js +3 -3
  97. package/lib/ip-restriction-jKtKCRM_.js +166 -0
  98. package/lib/ip-restriction.js +1 -165
  99. package/lib/ipaddr-DCoIo528.js +238 -0
  100. package/lib/jsx/dom/client.js +1 -1
  101. package/lib/jsx/dom/jsx-dev-runtime.js +1 -1
  102. package/lib/jsx/dom/jsx-runtime.js +2 -1
  103. package/lib/jsx/dom/server.js +3 -3
  104. package/lib/jsx/dom.js +5 -73
  105. package/lib/jsx/jsx-dev-runtime.d.ts +2 -5
  106. package/lib/jsx/jsx-dev-runtime.js +2 -13
  107. package/lib/jsx/jsx-runtime.d.ts +2 -2
  108. package/lib/jsx/jsx-runtime.js +4 -4
  109. package/lib/jsx/streaming.js +1 -1
  110. package/lib/jsx-CUQgttxU.js +47 -0
  111. package/lib/jsx-dev-runtime-B4WTyq8r.js +14 -0
  112. package/lib/{jsx-dev-runtime-CWLRA2F3.js → jsx-dev-runtime-BLfA-EhI.js} +2 -2
  113. package/lib/jsx-dev-runtime-CGt4kNYr.d.ts +6 -0
  114. package/lib/jsx-renderer-CfifM4hT.js +99 -0
  115. package/lib/jsx-renderer.js +1 -98
  116. package/lib/jsx-runtime-COCRWBJ9.js +2 -0
  117. package/lib/jsx.js +5 -46
  118. package/lib/{jwk-LkzeoaU8.js → jwk-CDPpYQpD.js} +3 -3
  119. package/lib/jwk.js +1 -1
  120. package/lib/{jwt-BGJBw5AF.js → jwt-BXoIA2fQ.js} +2 -2
  121. package/lib/{jwt-CskdhEW9.js → jwt-lyS4Q3mT.js} +3 -3
  122. package/lib/jwt.js +2 -2
  123. package/lib/kv/db.d.ts +1 -10
  124. package/lib/kv/db.js +1 -56
  125. package/lib/kv/json.d.ts +1 -9
  126. package/lib/kv/json.js +1 -223
  127. package/lib/{language-D9a4zqvn.js → language-DeGRtLJt.js} +2 -2
  128. package/lib/language.js +1 -1
  129. package/lib/{linear-router-C3FPib6h.js → linear-router-CmZn_JLV.js} +2 -2
  130. package/lib/logger-Ckxu8diz.js +54 -0
  131. package/lib/logger.js +1 -53
  132. package/lib/loopback-only-BbasoF7R.js +90 -0
  133. package/lib/loopback-only.js +1 -89
  134. package/lib/method-not-allowed-TO2_hnfl.js +82 -0
  135. package/lib/method-not-allowed.js +1 -81
  136. package/lib/method-override-DnZKfJbV.js +103 -0
  137. package/lib/method-override.js +1 -102
  138. package/lib/middleware-BfG_fp8P.js +12 -0
  139. package/lib/mime-BnScXkQn.js +77 -0
  140. package/lib/mount-QkK_3NtJ.js +67 -0
  141. package/lib/mount.js +1 -66
  142. package/lib/node-server/conninfo.d.ts +1 -10
  143. package/lib/node-server/conninfo.js +1 -18
  144. package/lib/node-server/register.js +25 -2
  145. package/lib/node-server/serve-static.d.ts +1 -17
  146. package/lib/node-server/serve-static.js +1 -1
  147. package/lib/node-server.d.ts +2 -2
  148. package/lib/node-server.js +4 -4
  149. package/lib/open-BqK4D2Wn.d.ts +11 -0
  150. package/lib/open-But9E2rL.js +57 -0
  151. package/lib/open-CULVJgOc.d.ts +12 -0
  152. package/lib/open-Dp4sxspc.js +224 -0
  153. package/lib/open-T7kgbO2O.d.ts +27 -0
  154. package/lib/{pattern-router-HZxjDGEQ.js → pattern-router-CJBecJBd.js} +1 -1
  155. package/lib/powered-by-CXQNjNIX.js +24 -0
  156. package/lib/powered-by.js +1 -23
  157. package/lib/pretty-json-CeC1yvYt.js +39 -0
  158. package/lib/pretty-json.js +1 -38
  159. package/lib/{protocol-BizVt4J6.d.ts → protocol-C37gPePD.d.ts} +9 -2
  160. package/lib/protocol-Dt0AZBOz.js +213 -0
  161. package/lib/proxy-C2w_mH7k.js +121 -0
  162. package/lib/proxy.js +1 -120
  163. package/lib/quick.js +4 -4
  164. package/lib/{reg-exp-router-DC1R3qoY.js → reg-exp-router-C_WV84eV.js} +2 -2
  165. package/lib/request-DvMgGtlW.js +323 -0
  166. package/lib/request.js +1 -322
  167. package/lib/route-D8m-a2I1.js +126 -0
  168. package/lib/route.js +1 -125
  169. package/lib/router/linear-router.js +1 -1
  170. package/lib/router/pattern-router.js +1 -1
  171. package/lib/router/reg-exp-router.js +1 -1
  172. package/lib/router/smart-router.js +1 -1
  173. package/lib/router/trie-router.js +1 -1
  174. package/lib/router-Be_o6nFu.js +35 -0
  175. package/lib/router.js +1 -34
  176. package/lib/schema-validator-EK3cUUCt.js +22 -0
  177. package/lib/schema-validator.js +1 -21
  178. package/lib/{secure-headers-mP3j6Hm6.js → secure-headers-C5ZOcXqk.js} +1 -1
  179. package/lib/secure-headers.js +1 -1
  180. package/lib/serve-static-B7sqnftW.d.ts +18 -0
  181. package/lib/{serve-static-3uo_9rjF.js → serve-static-C1Nkj_xB.js} +2 -2
  182. package/lib/{serve-static-Cp5adzGo.js → serve-static-EiJf1zkO.js} +4 -4
  183. package/lib/serve-static.js +1 -1
  184. package/lib/{smart-router-C5CZ5XSM.js → smart-router-BjxkDQCE.js} +1 -1
  185. package/lib/{snapshot-text-DmE0YfeZ.js → snapshot-text-Bbx43mN0.js} +57 -9
  186. package/lib/{src-2Z4mJg0x.js → src-BTBm4OPD.js} +22 -6
  187. package/lib/src-LX0E4ec4.js +117 -0
  188. package/lib/{ssg-BwjcA-Ge.js → ssg-BEl7MHqg.js} +5 -5
  189. package/lib/ssg.js +1 -1
  190. package/lib/stream-CzM_SHkq.js +88 -0
  191. package/lib/{streaming-DHST3Scg.js → streaming-BlDaph8U.js} +3 -3
  192. package/lib/streaming.js +1 -1
  193. package/lib/{test-websocket-D8WWqE5G.js → test-websocket-BLeEvybj.js} +2 -2
  194. package/lib/testing-BQx5T_UX.js +17 -0
  195. package/lib/testing.js +1 -16
  196. package/lib/timeout-FeqZ9A-0.js +42 -0
  197. package/lib/timeout.js +1 -41
  198. package/lib/tiny.js +2 -2
  199. package/lib/trailing-slash-DwTx-1sk.js +85 -0
  200. package/lib/trailing-slash.js +1 -84
  201. package/lib/{trie-router-CfFbapzL.js → trie-router-JydLKUa2.js} +2 -2
  202. package/lib/url-BPh4d6j-.js +197 -0
  203. package/lib/utils/accept.js +1 -192
  204. package/lib/utils/basic-auth.js +1 -19
  205. package/lib/utils/body.js +1 -93
  206. package/lib/utils/buffer.js +1 -50
  207. package/lib/utils/color.js +1 -36
  208. package/lib/utils/compress.d.ts +1 -10
  209. package/lib/utils/compress.js +1 -10
  210. package/lib/utils/concurrent.js +1 -29
  211. package/lib/utils/constants.js +1 -6
  212. package/lib/utils/cookie.js +1 -124
  213. package/lib/utils/crypto.js +1 -33
  214. package/lib/utils/encode.js +1 -32
  215. package/lib/utils/handler.js +1 -11
  216. package/lib/utils/html.js +1 -102
  217. package/lib/utils/ipaddr.js +1 -237
  218. package/lib/utils/jwt.js +1 -1
  219. package/lib/utils/mime.js +1 -76
  220. package/lib/utils/stream.js +1 -87
  221. package/lib/utils/url.js +1 -196
  222. package/lib/{validator-D84mq-dO.js → validator-Btiyt5VJ.js} +3 -3
  223. package/lib/validator.js +1 -1
  224. package/lib/websocket-DsyBIKVA.js +56 -0
  225. package/lib/ws.js +1 -55
  226. package/package.json +1 -1
  227. package/plugins/acryl-door/src/cli/acryl.ts +5 -3
  228. package/plugins/acryl-door/src/host/channel.ts +36 -0
  229. package/plugins/acryl-door/src/host/chat-tools.ts +2 -0
  230. package/plugins/acryl-door/src/host/door.ts +44 -5
  231. package/plugins/acryl-door/src/host/shim.ts +23 -0
  232. package/plugins/acryl-door/src/host/verbs.ts +4 -3
  233. package/plugins/acryl-door/src/index.ts +39 -3
  234. package/plugins/acryl-door/src/page/driver/driver.ts +22 -1
  235. package/plugins/acryl-door/src/page/protocol.ts +13 -2
  236. package/plugins/acryl-node-server/src/register.ts +29 -2
  237. package/plugins/acryl-router/src/service.ts +19 -1
  238. package/plugins/agent/model.ts +6 -1
  239. package/plugins/agent/tools.ts +12 -2
  240. package/plugins/agent-panel/client/describe.ts +44 -0
  241. package/plugins/agent-panel/client/main.ts +67 -35
  242. package/plugins/agent-panel/index.ts +137 -35
  243. package/plugins/desktop/attach.ts +72 -0
  244. package/plugins/desktop/main.ts +17 -4
  245. package/plugins/extensions/index.ts +3 -4
  246. package/plugins/extensions/stage.ts +33 -5
  247. package/plugins/openai/index.ts +1 -1
  248. package/shared/DEFAULTS.md +4 -0
  249. package/templates/agent/AGENTS.md +2 -0
  250. package/templates/agent/blend.yaml +4 -1
  251. package/templates/agent/src/app.ts +2 -0
  252. package/templates/agent/src/routes.ts +1 -1
  253. package/templates/agent/template.json +1 -0
  254. package/templates/agent/test/builder.test.ts +26 -21
  255. package/lib/helpers-CvTauQT5.js +0 -5
  256. package/lib/middleware-CPQ8himN.js +0 -12
@@ -0,0 +1,103 @@
1
+ //#region ../../plugins/acryl-router/src/core/utils/html.ts
2
+ /**
3
+ * @module
4
+ * HTML utility.
5
+ */
6
+ const HtmlEscapedCallbackPhase = {
7
+ Stringify: 1,
8
+ BeforeStream: 2,
9
+ Stream: 3
10
+ };
11
+ const raw = (value, callbacks) => {
12
+ const escapedString = new String(value);
13
+ escapedString.isEscaped = true;
14
+ escapedString.callbacks = callbacks;
15
+ return escapedString;
16
+ };
17
+ const escapeRe = /[&<>'"]/;
18
+ const stringBufferToString = async (buffer, callbacks) => {
19
+ let str = "";
20
+ callbacks ||= [];
21
+ const resolvedBuffer = await Promise.all(buffer);
22
+ for (let i = resolvedBuffer.length - 1;; i--) {
23
+ str += resolvedBuffer[i];
24
+ i--;
25
+ if (i < 0) break;
26
+ let r = resolvedBuffer[i];
27
+ if (typeof r === "object") callbacks.push(...r.callbacks || []);
28
+ const isEscaped = r.isEscaped;
29
+ r = await (typeof r === "object" ? r.toString() : r);
30
+ if (typeof r === "object") callbacks.push(...r.callbacks || []);
31
+ if (r.isEscaped ?? isEscaped) str += r;
32
+ else {
33
+ const buf = [str];
34
+ escapeToBuffer(r, buf);
35
+ str = buf[0];
36
+ }
37
+ }
38
+ return raw(str, callbacks);
39
+ };
40
+ const escapeToBuffer = (str, buffer) => {
41
+ const match = str.search(escapeRe);
42
+ if (match === -1) {
43
+ buffer[0] += str;
44
+ return;
45
+ }
46
+ let escape;
47
+ let index;
48
+ let lastIndex = 0;
49
+ for (index = match; index < str.length; index++) {
50
+ switch (str.charCodeAt(index)) {
51
+ case 34:
52
+ escape = "&quot;";
53
+ break;
54
+ case 39:
55
+ escape = "&#39;";
56
+ break;
57
+ case 38:
58
+ escape = "&amp;";
59
+ break;
60
+ case 60:
61
+ escape = "&lt;";
62
+ break;
63
+ case 62:
64
+ escape = "&gt;";
65
+ break;
66
+ default: continue;
67
+ }
68
+ buffer[0] += str.substring(lastIndex, index) + escape;
69
+ lastIndex = index + 1;
70
+ }
71
+ buffer[0] += str.substring(lastIndex, index);
72
+ };
73
+ const resolveCallbackSync = (str) => {
74
+ const callbacks = str.callbacks;
75
+ if (!callbacks?.length) return str;
76
+ const buffer = [str];
77
+ const context = {};
78
+ callbacks.forEach((c) => c({
79
+ phase: HtmlEscapedCallbackPhase.Stringify,
80
+ buffer,
81
+ context
82
+ }));
83
+ return buffer[0];
84
+ };
85
+ const resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
86
+ if (typeof str === "object" && !(str instanceof String)) {
87
+ if (!(str instanceof Promise)) str = str.toString();
88
+ if (str instanceof Promise) str = await str;
89
+ }
90
+ const callbacks = str.callbacks;
91
+ if (!callbacks?.length) return Promise.resolve(str);
92
+ if (buffer) buffer[0] += str;
93
+ else buffer = [str];
94
+ const resStr = Promise.all(callbacks.map((c) => c({
95
+ phase,
96
+ buffer,
97
+ context
98
+ }))).then((res) => Promise.all(res.filter(Boolean).map((str) => resolveCallback(str, phase, false, context, buffer))).then(() => buffer[0]));
99
+ if (preserveCallbacks) return raw(await resStr, callbacks);
100
+ else return resStr;
101
+ };
102
+ //#endregion
103
+ export { resolveCallbackSync as a, resolveCallback as i, escapeToBuffer as n, stringBufferToString as o, raw as r, HtmlEscapedCallbackPhase as t };
package/lib/html.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- import { c as raw, i as HtmlEscapedString } from "./html-SllAe0YT.js";
2
-
3
- //#region ../../plugins/acryl-router/src/core/helper/html/index.d.ts
4
- declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => HtmlEscapedString | Promise<HtmlEscapedString>;
5
- //#endregion
1
+ import { c as raw } from "./html-SllAe0YT.js";
2
+ import { t as html } from "./index-dAzQsJG9.js";
6
3
  export { html, raw };
package/lib/html.js CHANGED
@@ -1,31 +1,3 @@
1
- import { escapeToBuffer, raw, resolveCallbackSync, stringBufferToString } from "./utils/html.js";
2
- //#region ../../plugins/acryl-router/src/core/helper/html/index.ts
3
- /**
4
- * @module
5
- * html Helper for Acryl.
6
- */
7
- const html = (strings, ...values) => {
8
- const buffer = [""];
9
- for (let i = 0, len = strings.length - 1; i < len; i++) {
10
- buffer[0] += strings[i];
11
- const children = Array.isArray(values[i]) ? values[i].flat(Infinity) : [values[i]];
12
- for (let i = 0, len = children.length; i < len; i++) {
13
- const child = children[i];
14
- if (typeof child === "string") escapeToBuffer(child, buffer);
15
- else if (typeof child === "number") buffer[0] += child;
16
- else if (typeof child === "boolean" || child === null || child === void 0) continue;
17
- else if (typeof child === "object" && child.isEscaped) if (child.callbacks) buffer.unshift("", child);
18
- else {
19
- const tmp = child.toString();
20
- if (tmp instanceof Promise) buffer.unshift("", tmp);
21
- else buffer[0] += tmp;
22
- }
23
- else if (child instanceof Promise) buffer.unshift("", child);
24
- else escapeToBuffer(child.toString(), buffer);
25
- }
26
- }
27
- buffer[0] += strings.at(-1);
28
- return buffer.length === 1 ? "callbacks" in buffer ? raw(resolveCallbackSync(raw(buffer[0], buffer.callbacks))) : raw(buffer[0]) : stringBufferToString(buffer, buffer.callbacks);
29
- };
30
- //#endregion
1
+ import { r as raw } from "./html-DGExBFNg.js";
2
+ import { t as html } from "./html-CgNa89xw.js";
31
3
  export { html, raw };
@@ -0,0 +1,54 @@
1
+ //#region ../../plugins/acryl-router/src/core/http-exception.ts
2
+ /**
3
+ * `HTTPException` must be used when a fatal error such as authentication failure occurs.
4
+ *
5
+ *
6
+ * @param {StatusCode} status - status code of HTTPException
7
+ * @param {HTTPExceptionOptions} options - options of HTTPException
8
+ * @param {HTTPExceptionOptions["res"]} options.res - response of options of HTTPException
9
+ * @param {HTTPExceptionOptions["message"]} options.message - message of options of HTTPException
10
+ * @param {HTTPExceptionOptions["cause"]} options.cause - cause of options of HTTPException
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { HTTPException } from 'acrylblends/http-exception'
15
+ *
16
+ * // ...
17
+ *
18
+ * app.post('/auth', async (c, next) => {
19
+ * // authentication
20
+ * if (authorized === false) {
21
+ * throw new HTTPException(401, { message: 'Custom error message' })
22
+ * }
23
+ * await next()
24
+ * })
25
+ * ```
26
+ */
27
+ var HTTPException = class extends Error {
28
+ res;
29
+ status;
30
+ /**
31
+ * Creates an instance of `HTTPException`.
32
+ * @param status - HTTP status code for the exception. Defaults to 500.
33
+ * @param options - Additional options for the exception.
34
+ */
35
+ constructor(status = 500, options) {
36
+ super(options?.message, { cause: options?.cause });
37
+ this.res = options?.res;
38
+ this.status = status;
39
+ }
40
+ /**
41
+ * Returns the response object associated with the exception.
42
+ * If a response object is not provided, a new response is created with the error message and status code.
43
+ * @returns The response object.
44
+ */
45
+ getResponse() {
46
+ if (this.res) return new Response(this.res.body, {
47
+ status: this.status,
48
+ headers: this.res.headers
49
+ });
50
+ return new Response(this.message, { status: this.status });
51
+ }
52
+ };
53
+ //#endregion
54
+ export { HTTPException as t };
@@ -1,54 +1,2 @@
1
- //#region ../../plugins/acryl-router/src/core/http-exception.ts
2
- /**
3
- * `HTTPException` must be used when a fatal error such as authentication failure occurs.
4
- *
5
- *
6
- * @param {StatusCode} status - status code of HTTPException
7
- * @param {HTTPExceptionOptions} options - options of HTTPException
8
- * @param {HTTPExceptionOptions["res"]} options.res - response of options of HTTPException
9
- * @param {HTTPExceptionOptions["message"]} options.message - message of options of HTTPException
10
- * @param {HTTPExceptionOptions["cause"]} options.cause - cause of options of HTTPException
11
- *
12
- * @example
13
- * ```ts
14
- * import { HTTPException } from 'acrylblends/http-exception'
15
- *
16
- * // ...
17
- *
18
- * app.post('/auth', async (c, next) => {
19
- * // authentication
20
- * if (authorized === false) {
21
- * throw new HTTPException(401, { message: 'Custom error message' })
22
- * }
23
- * await next()
24
- * })
25
- * ```
26
- */
27
- var HTTPException = class extends Error {
28
- res;
29
- status;
30
- /**
31
- * Creates an instance of `HTTPException`.
32
- * @param status - HTTP status code for the exception. Defaults to 500.
33
- * @param options - Additional options for the exception.
34
- */
35
- constructor(status = 500, options) {
36
- super(options?.message, { cause: options?.cause });
37
- this.res = options?.res;
38
- this.status = status;
39
- }
40
- /**
41
- * Returns the response object associated with the exception.
42
- * If a response object is not provided, a new response is created with the error message and status code.
43
- * @returns The response object.
44
- */
45
- getResponse() {
46
- if (this.res) return new Response(this.res.body, {
47
- status: this.status,
48
- headers: this.res.headers
49
- });
50
- return new Response(this.message, { status: this.status });
51
- }
52
- };
53
- //#endregion
1
+ import { t as HTTPException } from "./http-exception-MjWkT89V.js";
54
2
  export { HTTPException };
@@ -1,4 +1,4 @@
1
- import { B as NotFoundHandler, y as ErrorHandler } from "./context-DS3fYyG-.js";
1
+ import { B as NotFoundHandler, E as H, y as ErrorHandler } from "./context-DS3fYyG-.js";
2
2
  import { t as ConnectionInfo } from "./connection-ZLEso7XL.js";
3
3
  import { n as UpgradeWebSocket } from "./index-C-SklY6u.js";
4
4
  import { Context, Service } from "@deepseek-ai/cordis";
@@ -77,6 +77,12 @@ declare class Router extends Service {
77
77
  * are copied now: one the app registers after this call is not served (mount again, or finish the app first).
78
78
  */
79
79
  route(path: string, app: MountableApp): () => void;
80
+ /**
81
+ * Run `middleware` around every request the router serves, whenever the plugin that asks was mounted: a middleware in a plain mount wraps only the routes mounted after it,
82
+ * which is the wrong tool for a plugin that must see every page (the door adds its script to each HTML response, the pages of a plugin that loaded earlier included). It goes
83
+ * outside all mounts, in the order wrappers were added, and goes away when the calling plugin unloads or when the returned function is called.
84
+ */
85
+ wrap(middleware: H): () => void;
80
86
  /**
81
87
  * The mount's own copy of `app`'s routes as they are now (like the core's `app.route`), each handler wrapped so the router knows which
82
88
  * mount's code a request is in. The core's `app.route` runs first so a sub-app's own `onError` still applies to its routes.
@@ -0,0 +1,6 @@
1
+ import { i as HtmlEscapedString } from "./html-SllAe0YT.js";
2
+
3
+ //#region ../../plugins/acryl-router/src/core/helper/html/index.d.ts
4
+ declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => HtmlEscapedString | Promise<HtmlEscapedString>;
5
+ //#endregion
6
+ export { html as t };
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as Context } from "./context-DDO0cfuP.js";
2
- import { t as Acryl } from "./app-BM0rTCp7.js";
3
- import "./core-CaY8XDZ6.js";
1
+ import { t as Context } from "./context-CkOh7Ygv.js";
2
+ import { t as Acryl } from "./app-CQcGWjrk.js";
3
+ import "./core-BOu1jYua.js";
4
4
  export { Acryl, Context };
@@ -0,0 +1,166 @@
1
+ import { t as HTTPException } from "./http-exception-MjWkT89V.js";
2
+ import { a as convertIPv6BinaryToString, i as convertIPv4ToBinary, l as isIPv4MappedIPv6, o as convertIPv6ToBinary, r as convertIPv4MappedIPv6ToIPv4, s as distinctRemoteAddr } from "./ipaddr-DCoIo528.js";
3
+ //#region ../../plugins/acryl-router/src/core/middleware/ip-restriction/index.ts
4
+ const IS_CIDR_NOTATION_REGEX = /\/[^/]*$/;
5
+ const parseCidrPrefix = (rule, prefix, max) => {
6
+ if (!/^[0-9]{1,3}$/.test(prefix)) throw new TypeError(`Invalid rule: ${rule}`);
7
+ const parsedPrefix = parseInt(prefix);
8
+ if (parsedPrefix > max) throw new TypeError(`Invalid rule: ${rule}`);
9
+ return parsedPrefix;
10
+ };
11
+ const buildMatcher = (rules) => {
12
+ const functionRules = [];
13
+ const staticRules = /* @__PURE__ */ new Set();
14
+ const staticIPv4Rules = /* @__PURE__ */ new Set();
15
+ const staticIPv6Rules = /* @__PURE__ */ new Set();
16
+ const cidrRules = [];
17
+ const registerStaticRule = (rule) => {
18
+ const type = distinctRemoteAddr(rule);
19
+ if (type === void 0) throw new TypeError(`Invalid rule: ${rule}`);
20
+ if (type === "IPv4") {
21
+ const ipv4binary = convertIPv4ToBinary(rule);
22
+ staticRules.add(rule);
23
+ staticRules.add(`::ffff:${rule}`);
24
+ staticIPv4Rules.add(ipv4binary);
25
+ staticIPv6Rules.add(65535n << 32n | ipv4binary);
26
+ } else {
27
+ const ipv6binary = convertIPv6ToBinary(rule);
28
+ const ipv6Addr = convertIPv6BinaryToString(ipv6binary);
29
+ staticRules.add(ipv6Addr);
30
+ staticIPv6Rules.add(ipv6binary);
31
+ if (isIPv4MappedIPv6(ipv6binary)) {
32
+ staticRules.add(ipv6Addr.substring(7));
33
+ staticIPv4Rules.add(convertIPv4MappedIPv6ToIPv4(ipv6binary));
34
+ }
35
+ }
36
+ };
37
+ for (let rule of rules) if (rule === "*") return () => true;
38
+ else if (typeof rule === "function") functionRules.push(rule);
39
+ else {
40
+ if (IS_CIDR_NOTATION_REGEX.test(rule)) {
41
+ const separatedRule = rule.split("/");
42
+ const addrStr = separatedRule[0];
43
+ const type = distinctRemoteAddr(addrStr);
44
+ if (type === void 0) throw new TypeError(`Invalid rule: ${rule}`);
45
+ let isIPv4 = type === "IPv4";
46
+ let prefix = parseCidrPrefix(rule, separatedRule[1], isIPv4 ? 32 : 128);
47
+ if (isIPv4 ? prefix === 32 : prefix === 128) rule = addrStr;
48
+ else {
49
+ let addr = (isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(addrStr);
50
+ if (type === "IPv6" && isIPv4MappedIPv6(addr) && prefix >= 96) {
51
+ isIPv4 = true;
52
+ addr = convertIPv4MappedIPv6ToIPv4(addr);
53
+ prefix -= 96;
54
+ }
55
+ const mask = (1n << BigInt(prefix)) - 1n << BigInt((isIPv4 ? 32 : 128) - prefix);
56
+ cidrRules.push([
57
+ isIPv4,
58
+ addr & mask,
59
+ mask
60
+ ]);
61
+ continue;
62
+ }
63
+ }
64
+ registerStaticRule(rule);
65
+ }
66
+ return (remote) => {
67
+ if (staticRules.has(remote.addr)) return true;
68
+ const remoteAddr = remote.binaryAddr ||= (remote.isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(remote.addr);
69
+ const remoteIPv4Addr = remote.isIPv4 || isIPv4MappedIPv6(remoteAddr) ? remote.isIPv4 ? remoteAddr : convertIPv4MappedIPv6ToIPv4(remoteAddr) : void 0;
70
+ if ((remote.isIPv4 ? staticIPv4Rules : staticIPv6Rules).has(remoteAddr)) return true;
71
+ for (const [isIPv4, addr, mask] of cidrRules) {
72
+ if (isIPv4) {
73
+ if (remoteIPv4Addr === void 0) continue;
74
+ if ((remoteIPv4Addr & mask) === addr) return true;
75
+ continue;
76
+ }
77
+ if (remote.isIPv4) continue;
78
+ if ((remoteAddr & mask) === addr) return true;
79
+ }
80
+ for (const rule of functionRules) if (rule({
81
+ addr: remote.addr,
82
+ type: remote.type
83
+ })) return true;
84
+ return false;
85
+ };
86
+ };
87
+ /**
88
+ * IP Restriction Middleware for Acryl.
89
+ *
90
+ *
91
+ * @param {GetConnInfo | ((c: Context) => string)} getIP - A function to retrieve the client IP address. Use `getConnInfo` from the appropriate runtime adapter.
92
+ * @param {IPRestrictionRules} rules - An object with optional `denyList` and `allowList` arrays of IP rules. Each rule can be a static IP, a CIDR range, or a custom function.
93
+ * @param {(remote: { addr: string; type: AddressType }, c: Context) => Response | Promise<Response>} [onError] - Optional custom handler invoked when a request is blocked. Defaults to returning a 403 Forbidden response.
94
+ * @returns {MiddlewareHandler} The middleware handler function.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * import { Acryl } from 'acrylblends'
99
+ * import { ipRestriction } from 'acrylblends/ip-restriction'
100
+ * import { getConnInfo } from 'acrylblends/cloudflare-workers'
101
+ *
102
+ * const app = new Acryl()
103
+ *
104
+ * app.use(
105
+ * '*',
106
+ * ipRestriction(getConnInfo, {
107
+ * // Block a specific IP and an entire subnet
108
+ * denyList: ['192.168.0.5', '10.0.0.0/8'],
109
+ * // Only allow requests from localhost and a private range
110
+ * allowList: ['127.0.0.1', '::1', '192.168.1.0/24'],
111
+ * })
112
+ * )
113
+ *
114
+ * // With a custom error handler
115
+ * app.use(
116
+ * '/admin/*',
117
+ * ipRestriction(
118
+ * getConnInfo,
119
+ * { allowList: ['203.0.113.0/24'] },
120
+ * (remote, c) => c.text(`Access denied for ${remote.addr}`, 403)
121
+ * )
122
+ * )
123
+ *
124
+ * app.get('/', (c) => c.text('Hello!'))
125
+ * ```
126
+ */
127
+ const ipRestriction = (getIP, { denyList = [], allowList = [] }, onError) => {
128
+ const allowLength = allowList.length;
129
+ const denyMatcher = buildMatcher(denyList);
130
+ const allowMatcher = buildMatcher(allowList);
131
+ const blockError = (c) => new HTTPException(403, { res: c.text("Forbidden", { status: 403 }) });
132
+ return async function ipRestriction(c, next) {
133
+ const connInfo = getIP(c);
134
+ const addr = typeof connInfo === "string" ? connInfo : connInfo.remote.address;
135
+ if (!addr) throw blockError(c);
136
+ const type = typeof connInfo !== "string" && connInfo.remote.addressType || distinctRemoteAddr(addr);
137
+ const remoteData = {
138
+ addr,
139
+ type,
140
+ isIPv4: type === "IPv4"
141
+ };
142
+ try {
143
+ if (denyMatcher(remoteData)) {
144
+ if (onError) return onError({
145
+ addr,
146
+ type
147
+ }, c);
148
+ throw blockError(c);
149
+ }
150
+ if (allowMatcher(remoteData)) return await next();
151
+ } catch (e) {
152
+ if (e instanceof TypeError && e.code === "ERR_INVALID_IP_ADDRESS") throw blockError(c);
153
+ throw e;
154
+ }
155
+ if (allowLength === 0) return await next();
156
+ else {
157
+ if (onError) return await onError({
158
+ addr,
159
+ type
160
+ }, c);
161
+ throw blockError(c);
162
+ }
163
+ };
164
+ };
165
+ //#endregion
166
+ export { ipRestriction as t };
@@ -1,166 +1,2 @@
1
- import { HTTPException } from "./http-exception.js";
2
- import { convertIPv4MappedIPv6ToIPv4, convertIPv4ToBinary, convertIPv6BinaryToString, convertIPv6ToBinary, distinctRemoteAddr, isIPv4MappedIPv6 } from "./utils/ipaddr.js";
3
- //#region ../../plugins/acryl-router/src/core/middleware/ip-restriction/index.ts
4
- const IS_CIDR_NOTATION_REGEX = /\/[^/]*$/;
5
- const parseCidrPrefix = (rule, prefix, max) => {
6
- if (!/^[0-9]{1,3}$/.test(prefix)) throw new TypeError(`Invalid rule: ${rule}`);
7
- const parsedPrefix = parseInt(prefix);
8
- if (parsedPrefix > max) throw new TypeError(`Invalid rule: ${rule}`);
9
- return parsedPrefix;
10
- };
11
- const buildMatcher = (rules) => {
12
- const functionRules = [];
13
- const staticRules = /* @__PURE__ */ new Set();
14
- const staticIPv4Rules = /* @__PURE__ */ new Set();
15
- const staticIPv6Rules = /* @__PURE__ */ new Set();
16
- const cidrRules = [];
17
- const registerStaticRule = (rule) => {
18
- const type = distinctRemoteAddr(rule);
19
- if (type === void 0) throw new TypeError(`Invalid rule: ${rule}`);
20
- if (type === "IPv4") {
21
- const ipv4binary = convertIPv4ToBinary(rule);
22
- staticRules.add(rule);
23
- staticRules.add(`::ffff:${rule}`);
24
- staticIPv4Rules.add(ipv4binary);
25
- staticIPv6Rules.add(65535n << 32n | ipv4binary);
26
- } else {
27
- const ipv6binary = convertIPv6ToBinary(rule);
28
- const ipv6Addr = convertIPv6BinaryToString(ipv6binary);
29
- staticRules.add(ipv6Addr);
30
- staticIPv6Rules.add(ipv6binary);
31
- if (isIPv4MappedIPv6(ipv6binary)) {
32
- staticRules.add(ipv6Addr.substring(7));
33
- staticIPv4Rules.add(convertIPv4MappedIPv6ToIPv4(ipv6binary));
34
- }
35
- }
36
- };
37
- for (let rule of rules) if (rule === "*") return () => true;
38
- else if (typeof rule === "function") functionRules.push(rule);
39
- else {
40
- if (IS_CIDR_NOTATION_REGEX.test(rule)) {
41
- const separatedRule = rule.split("/");
42
- const addrStr = separatedRule[0];
43
- const type = distinctRemoteAddr(addrStr);
44
- if (type === void 0) throw new TypeError(`Invalid rule: ${rule}`);
45
- let isIPv4 = type === "IPv4";
46
- let prefix = parseCidrPrefix(rule, separatedRule[1], isIPv4 ? 32 : 128);
47
- if (isIPv4 ? prefix === 32 : prefix === 128) rule = addrStr;
48
- else {
49
- let addr = (isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(addrStr);
50
- if (type === "IPv6" && isIPv4MappedIPv6(addr) && prefix >= 96) {
51
- isIPv4 = true;
52
- addr = convertIPv4MappedIPv6ToIPv4(addr);
53
- prefix -= 96;
54
- }
55
- const mask = (1n << BigInt(prefix)) - 1n << BigInt((isIPv4 ? 32 : 128) - prefix);
56
- cidrRules.push([
57
- isIPv4,
58
- addr & mask,
59
- mask
60
- ]);
61
- continue;
62
- }
63
- }
64
- registerStaticRule(rule);
65
- }
66
- return (remote) => {
67
- if (staticRules.has(remote.addr)) return true;
68
- const remoteAddr = remote.binaryAddr ||= (remote.isIPv4 ? convertIPv4ToBinary : convertIPv6ToBinary)(remote.addr);
69
- const remoteIPv4Addr = remote.isIPv4 || isIPv4MappedIPv6(remoteAddr) ? remote.isIPv4 ? remoteAddr : convertIPv4MappedIPv6ToIPv4(remoteAddr) : void 0;
70
- if ((remote.isIPv4 ? staticIPv4Rules : staticIPv6Rules).has(remoteAddr)) return true;
71
- for (const [isIPv4, addr, mask] of cidrRules) {
72
- if (isIPv4) {
73
- if (remoteIPv4Addr === void 0) continue;
74
- if ((remoteIPv4Addr & mask) === addr) return true;
75
- continue;
76
- }
77
- if (remote.isIPv4) continue;
78
- if ((remoteAddr & mask) === addr) return true;
79
- }
80
- for (const rule of functionRules) if (rule({
81
- addr: remote.addr,
82
- type: remote.type
83
- })) return true;
84
- return false;
85
- };
86
- };
87
- /**
88
- * IP Restriction Middleware for Acryl.
89
- *
90
- *
91
- * @param {GetConnInfo | ((c: Context) => string)} getIP - A function to retrieve the client IP address. Use `getConnInfo` from the appropriate runtime adapter.
92
- * @param {IPRestrictionRules} rules - An object with optional `denyList` and `allowList` arrays of IP rules. Each rule can be a static IP, a CIDR range, or a custom function.
93
- * @param {(remote: { addr: string; type: AddressType }, c: Context) => Response | Promise<Response>} [onError] - Optional custom handler invoked when a request is blocked. Defaults to returning a 403 Forbidden response.
94
- * @returns {MiddlewareHandler} The middleware handler function.
95
- *
96
- * @example
97
- * ```ts
98
- * import { Acryl } from 'acrylblends'
99
- * import { ipRestriction } from 'acrylblends/ip-restriction'
100
- * import { getConnInfo } from 'acrylblends/cloudflare-workers'
101
- *
102
- * const app = new Acryl()
103
- *
104
- * app.use(
105
- * '*',
106
- * ipRestriction(getConnInfo, {
107
- * // Block a specific IP and an entire subnet
108
- * denyList: ['192.168.0.5', '10.0.0.0/8'],
109
- * // Only allow requests from localhost and a private range
110
- * allowList: ['127.0.0.1', '::1', '192.168.1.0/24'],
111
- * })
112
- * )
113
- *
114
- * // With a custom error handler
115
- * app.use(
116
- * '/admin/*',
117
- * ipRestriction(
118
- * getConnInfo,
119
- * { allowList: ['203.0.113.0/24'] },
120
- * (remote, c) => c.text(`Access denied for ${remote.addr}`, 403)
121
- * )
122
- * )
123
- *
124
- * app.get('/', (c) => c.text('Hello!'))
125
- * ```
126
- */
127
- const ipRestriction = (getIP, { denyList = [], allowList = [] }, onError) => {
128
- const allowLength = allowList.length;
129
- const denyMatcher = buildMatcher(denyList);
130
- const allowMatcher = buildMatcher(allowList);
131
- const blockError = (c) => new HTTPException(403, { res: c.text("Forbidden", { status: 403 }) });
132
- return async function ipRestriction(c, next) {
133
- const connInfo = getIP(c);
134
- const addr = typeof connInfo === "string" ? connInfo : connInfo.remote.address;
135
- if (!addr) throw blockError(c);
136
- const type = typeof connInfo !== "string" && connInfo.remote.addressType || distinctRemoteAddr(addr);
137
- const remoteData = {
138
- addr,
139
- type,
140
- isIPv4: type === "IPv4"
141
- };
142
- try {
143
- if (denyMatcher(remoteData)) {
144
- if (onError) return onError({
145
- addr,
146
- type
147
- }, c);
148
- throw blockError(c);
149
- }
150
- if (allowMatcher(remoteData)) return await next();
151
- } catch (e) {
152
- if (e instanceof TypeError && e.code === "ERR_INVALID_IP_ADDRESS") throw blockError(c);
153
- throw e;
154
- }
155
- if (allowLength === 0) return await next();
156
- else {
157
- if (onError) return await onError({
158
- addr,
159
- type
160
- }, c);
161
- throw blockError(c);
162
- }
163
- };
164
- };
165
- //#endregion
1
+ import { t as ipRestriction } from "./ip-restriction-jKtKCRM_.js";
166
2
  export { ipRestriction };