@rho-workspace/rho 0.5.5 → 0.5.6

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 (106) hide show
  1. package/dist/agent-connect.d.ts +8 -0
  2. package/dist/agent-connect.js +15 -0
  3. package/dist/browser-access.js +1 -1
  4. package/dist/cli.js +38 -8
  5. package/dist/contract.generated.d.ts +148 -5
  6. package/dist/contract.generated.js +1 -1
  7. package/dist/contracts/owners.generated.js +107 -12
  8. package/dist/conversations.d.ts +157 -4
  9. package/dist/conversations.js +69 -6
  10. package/dist/discovery.js +1 -1
  11. package/dist/protocol.d.ts +1 -0
  12. package/dist/protocol.js +12 -5
  13. package/dist/server.d.ts +2 -10
  14. package/dist/server.js +71 -8
  15. package/dist/web/.vite/manifest.json +61 -61
  16. package/dist/web/assets/{choices-b0XhrGQV.js → choices-D-YfnFP6.js} +1 -1
  17. package/dist/web/assets/{console-BSjLGe0T.js → console-Trqc0swD.js} +1 -1
  18. package/dist/web/assets/{dist-Buk0lwzI.js → dist-DZmszrjG.js} +1 -1
  19. package/dist/web/assets/{dist-Cw8hRIlT.js → dist-DpIHRk3B.js} +1 -1
  20. package/dist/web/assets/{dist-foH9IKc6.js → dist-eMx6b8N1.js} +1 -1
  21. package/dist/web/assets/{dist-Tzoe_zm-.js → dist-pF902jHA.js} +1 -1
  22. package/dist/web/assets/{explore-in-BVUy3ZW_.js → explore-in-BCHqjJ7B.js} +1 -1
  23. package/dist/web/assets/{graph-1OdIJ9l7.js → graph-lENgfQNH.js} +1 -1
  24. package/dist/web/assets/index-B3_OVy91.css +1 -0
  25. package/dist/web/assets/{index-CxmItXqa.js → index-BpL_Kl_s.js} +84 -83
  26. package/dist/web/assets/{notes-meaning-pVbbQUGP.js → notes-meaning-DcVGUBBY.js} +1 -1
  27. package/dist/web/assets/{overview-B9UtVJ32.js → overview-CDnVKlOt.js} +3 -3
  28. package/dist/web/assets/{preview-CksD_5KS.js → preview-BEC1E9MK.js} +1 -1
  29. package/dist/web/assets/{review-CMxQlQ-C.js → review-DYP0aCXb.js} +1 -1
  30. package/dist/web/assets/{skills-BFNSyrnD.js → skills-1ec0Z-jx.js} +1 -1
  31. package/dist/web/assets/{skills-work-BGPSnF_I.js → skills-work-DNexV4OJ.js} +1 -1
  32. package/dist/web/assets/{studio-process-CsRoTHOh.js → studio-process-EYQgikxq.js} +1 -1
  33. package/dist/web/assets/{timeline-events-BbuuFWHV.js → timeline-events-Chj2Gbx7.js} +1 -1
  34. package/dist/web/assets/{work-turns-BvJlIMmA.js → work-turns-CT9RVcWY.js} +1 -1
  35. package/dist/web/assets/{workspace-CWlkjLNx.js → workspace-COmCbGV3.js} +1 -1
  36. package/dist/web/composition.json +58 -58
  37. package/dist/web/index.html +2 -2
  38. package/dist/web/renderer.json +1 -1
  39. package/docs/FRONTEND.md +26 -18
  40. package/docs/HEADLESS.md +37 -27
  41. package/node_modules/@rho-workspace/plugin-agent/README.md +29 -0
  42. package/node_modules/@rho-workspace/plugin-agent/dist/acp-command.d.ts +1 -0
  43. package/node_modules/@rho-workspace/plugin-agent/dist/acp-command.js +9 -1
  44. package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.d.ts +1 -0
  45. package/node_modules/@rho-workspace/plugin-agent/dist/acp-conversation.js +10 -0
  46. package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.js +10 -5
  47. package/node_modules/@rho-workspace/plugin-agent/dist/external-session.d.ts +12 -1
  48. package/node_modules/@rho-workspace/plugin-agent/dist/native-sessions.d.ts +70 -0
  49. package/node_modules/@rho-workspace/plugin-agent/dist/native-sessions.js +538 -0
  50. package/node_modules/@rho-workspace/plugin-agent/package.json +2 -1
  51. package/node_modules/hono/dist/adapter/aws-lambda/handler.js +1 -1
  52. package/node_modules/hono/dist/cjs/adapter/aws-lambda/handler.js +1 -1
  53. package/node_modules/hono/dist/cjs/adapter/bun/serve-static.js +1 -1
  54. package/node_modules/hono/dist/cjs/adapter/bun/websocket.js +1 -1
  55. package/node_modules/hono/dist/cjs/client/fetch-result-please.js +1 -1
  56. package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +2 -1
  57. package/node_modules/hono/dist/cjs/helper/ssg/ssg.js +5 -3
  58. package/node_modules/hono/dist/cjs/jsx/base.js +49 -30
  59. package/node_modules/hono/dist/cjs/jsx/components.js +2 -2
  60. package/node_modules/hono/dist/cjs/jsx/constants.js +2 -0
  61. package/node_modules/hono/dist/cjs/jsx/jsx-runtime.js +13 -17
  62. package/node_modules/hono/dist/cjs/middleware/etag/index.js +3 -1
  63. package/node_modules/hono/dist/cjs/middleware/pretty-json/index.js +1 -0
  64. package/node_modules/hono/dist/cjs/middleware/timing/timing.js +4 -3
  65. package/node_modules/hono/dist/cjs/utils/cookie.js +2 -2
  66. package/node_modules/hono/dist/cjs/utils/mime.js +1 -1
  67. package/node_modules/hono/dist/cjs/utils/url.js +1 -1
  68. package/node_modules/hono/dist/client/fetch-result-please.js +1 -1
  69. package/node_modules/hono/dist/helper/accepts/accepts.js +2 -1
  70. package/node_modules/hono/dist/helper/ssg/ssg.js +5 -3
  71. package/node_modules/hono/dist/jsx/base.js +49 -32
  72. package/node_modules/hono/dist/jsx/components.js +2 -2
  73. package/node_modules/hono/dist/jsx/constants.js +2 -1
  74. package/node_modules/hono/dist/jsx/jsx-runtime.js +15 -19
  75. package/node_modules/hono/dist/middleware/etag/index.js +3 -1
  76. package/node_modules/hono/dist/middleware/language/language.js +1 -1
  77. package/node_modules/hono/dist/middleware/pretty-json/index.js +1 -0
  78. package/node_modules/hono/dist/middleware/timing/timing.js +4 -3
  79. package/node_modules/hono/dist/utils/cookie.js +2 -2
  80. package/node_modules/hono/dist/utils/mime.js +1 -1
  81. package/node_modules/hono/dist/utils/url.js +1 -1
  82. package/node_modules/hono/package.json +1 -1
  83. package/package.json +2 -2
  84. package/protocol/index.json +39 -33
  85. package/protocol/operations/agent.sessions.list.json +49 -3
  86. package/protocol/operations/agent.sessions.read.json +53 -4
  87. package/protocol/operations/conversation.configure.json +29 -0
  88. package/protocol/operations/conversation.decide.json +29 -0
  89. package/protocol/operations/conversation.list.json +29 -0
  90. package/protocol/operations/conversation.permission.json +29 -0
  91. package/protocol/operations/conversation.read.json +29 -0
  92. package/protocol/operations/conversation.restore.json +29 -0
  93. package/protocol/operations/conversation.send.json +29 -0
  94. package/protocol/operations/conversation.settings.check.json +92 -0
  95. package/protocol/operations/conversation.settings.read.json +92 -0
  96. package/protocol/operations/conversation.settings.update.json +92 -0
  97. package/protocol/operations/conversation.start.json +46 -1
  98. package/protocol/operations/conversation.stop.json +29 -0
  99. package/protocol/operations/conversation.trash.json +29 -0
  100. package/protocol/operations/observation.snapshot.json +29 -0
  101. package/protocol/operations/session.instructions.json +43 -0
  102. package/vendor/composition.json +74 -74
  103. package/vendor/rho-workspace-plugin-agent-0.4.30.tgz +0 -0
  104. package/web/theme.css +12 -0
  105. package/dist/web/assets/index-CsC3sTRq.css +0 -1
  106. package/vendor/rho-workspace-plugin-agent-0.4.29.tgz +0 -0
@@ -26,7 +26,7 @@ const emptyTags = [
26
26
  "track",
27
27
  "wbr"
28
28
  ];
29
- const booleanAttributes = [
29
+ const booleanAttributes = /* @__PURE__ */ new Set([
30
30
  "allowfullscreen",
31
31
  "async",
32
32
  "autofocus",
@@ -52,8 +52,11 @@ const booleanAttributes = [
52
52
  "readonly",
53
53
  "required",
54
54
  "reversed",
55
- "selected"
56
- ];
55
+ "selected",
56
+ "shadowrootclonable",
57
+ "shadowrootdelegatesfocus",
58
+ "shadowrootserializable"
59
+ ]);
57
60
  const resolveFunctionComponentResult = (result, suspendedContext) => result.then((resolved) => {
58
61
  if (typeof resolved !== "string" && !Array.isArray(resolved) && !(resolved instanceof JSXNode)) return resolved;
59
62
  const children = Array.isArray(resolved) ? resolved : [resolved];
@@ -64,6 +67,44 @@ const resolveFunctionComponentResult = (result, suspendedContext) => result.then
64
67
  };
65
68
  return suspendedContext ? suspendedContext(render) : require_jsx_context.runWithRenderContext(render);
66
69
  });
70
+ const markRenderedJSX = (value) => {
71
+ value[require_jsx_constants.RENDERED_JSX] = true;
72
+ return value;
73
+ };
74
+ const isEscapedAttribute = (value) => value instanceof String && value.isEscaped && !(require_jsx_constants.RENDERED_JSX in value);
75
+ const objectToAttributeString = (v) => {
76
+ const s = v.toString();
77
+ return s instanceof Promise ? s.then(String) : String(s);
78
+ };
79
+ const attributeToBuffer = (buffer, prefix, key, v, tag) => {
80
+ if (key === "ref" || v === null || v === void 0) return;
81
+ if (typeof v === "boolean" && booleanAttributes.has(key)) {
82
+ if (v) buffer[0] += `${prefix}${key}=""`;
83
+ return;
84
+ }
85
+ if (typeof v === "function") {
86
+ if (!key.startsWith("on")) throw new Error(`Invalid prop '${key}' of type 'function' supplied to ${tag ? `'${tag}'` : "a JSX element"}.`);
87
+ return;
88
+ }
89
+ buffer[0] += `${prefix}${key}="`;
90
+ if (key === "style" && typeof v === "object") {
91
+ let styleStr = "";
92
+ require_jsx_utils.styleObjectForEach(v, (property, value) => {
93
+ if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
94
+ });
95
+ require_utils_html.escapeToBuffer(styleStr, buffer);
96
+ } else if (typeof v === "string") require_utils_html.escapeToBuffer(v, buffer);
97
+ else if (typeof v === "number" || isEscapedAttribute(v)) buffer[0] += `${v}`;
98
+ else {
99
+ const s = v instanceof Promise ? v.then((r) => typeof r === "object" && r !== null && !isEscapedAttribute(r) ? objectToAttributeString(r) : r) : objectToAttributeString(v);
100
+ if (s instanceof Promise) {
101
+ buffer.unshift("\"", s);
102
+ return;
103
+ }
104
+ require_utils_html.escapeToBuffer(s, buffer);
105
+ }
106
+ buffer[0] += "\"";
107
+ };
67
108
  const childrenToStringToBuffer = (children, buffer) => {
68
109
  for (let i = 0, len = children.length; i < len; i++) {
69
110
  const child = children[i];
@@ -115,7 +156,7 @@ var JSXNode = class {
115
156
  const render = () => {
116
157
  const buffer = [""];
117
158
  this.toStringToBuffer(buffer);
118
- return buffer.length === 1 ? "callbacks" in buffer ? require_utils_html.resolveCallbackSync(require_utils_html.raw(buffer[0], buffer.callbacks)).toString() : buffer[0] : require_utils_html.stringBufferToString(buffer, buffer.callbacks);
159
+ return buffer.length === 1 ? "callbacks" in buffer ? require_utils_html.resolveCallbackSync(require_utils_html.raw(buffer[0], buffer.callbacks)).toString() : buffer[0] : require_utils_html.stringBufferToString(buffer, buffer.callbacks).then(markRenderedJSX);
119
160
  };
120
161
  return require_jsx_context.runWithRenderContext(render);
121
162
  }
@@ -128,34 +169,10 @@ var JSXNode = class {
128
169
  for (let [key, v] of Object.entries(props)) {
129
170
  key = normalizeKey(key);
130
171
  if (!require_jsx_utils.isValidAttributeName(key)) continue;
131
- if (key === "children") {} else if (key === "style" && typeof v === "object") {
132
- let styleStr = "";
133
- require_jsx_utils.styleObjectForEach(v, (property, value) => {
134
- if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
135
- });
136
- buffer[0] += " style=\"";
137
- require_utils_html.escapeToBuffer(styleStr, buffer);
138
- buffer[0] += "\"";
139
- } else if (typeof v === "string") {
140
- buffer[0] += ` ${key}="`;
141
- require_utils_html.escapeToBuffer(v, buffer);
142
- buffer[0] += "\"";
143
- } else if (v === null || v === void 0) {} else if (typeof v === "number" || v.isEscaped) buffer[0] += ` ${key}="${v}"`;
144
- else if (typeof v === "boolean" && booleanAttributes.includes(key)) {
145
- if (v) buffer[0] += ` ${key}=""`;
146
- } else if (key === "dangerouslySetInnerHTML") {
172
+ if (key === "children") {} else if (key === "dangerouslySetInnerHTML" && typeof v === "object" && v !== null && "__html" in v) {
147
173
  if (children.length > 0) throw new Error("Can only set one of `children` or `props.dangerouslySetInnerHTML`.");
148
174
  children = [require_utils_html.raw(v.__html)];
149
- } else if (v instanceof Promise) {
150
- buffer[0] += ` ${key}="`;
151
- buffer.unshift("\"", v);
152
- } else if (typeof v === "function") {
153
- if (!key.startsWith("on") && key !== "ref") throw new Error(`Invalid prop '${key}' of type 'function' supplied to '${tag}'.`);
154
- } else {
155
- buffer[0] += ` ${key}="`;
156
- require_utils_html.escapeToBuffer(v.toString(), buffer);
157
- buffer[0] += "\"";
158
- }
175
+ } else attributeToBuffer(buffer, " ", key, v, tag);
159
176
  }
160
177
  if (emptyTags.includes(tag) && children.length === 0) {
161
178
  buffer[0] += "/>";
@@ -252,6 +269,7 @@ const reactAPICompatVersion = "19.0.0-hono-jsx";
252
269
  exports.Fragment = Fragment;
253
270
  exports.JSXFragmentNode = JSXFragmentNode;
254
271
  exports.JSXNode = JSXNode;
272
+ exports.attributeToBuffer = attributeToBuffer;
255
273
  exports.booleanAttributes = booleanAttributes;
256
274
  exports.cloneElement = cloneElement;
257
275
  exports.getNameSpaceContext = getNameSpaceContext;
@@ -259,6 +277,7 @@ exports.isUntrustedObject = isUntrustedObject;
259
277
  exports.isValidElement = isValidElement;
260
278
  exports.jsx = jsx;
261
279
  exports.jsxFn = jsxFn;
280
+ exports.markRenderedJSX = markRenderedJSX;
262
281
  exports.memo = memo;
263
282
  exports.reactAPICompatVersion = reactAPICompatVersion;
264
283
  exports.renderChildren = renderChildren;
@@ -78,7 +78,7 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
78
78
  buffer[0] = buffer[0].replace(replaceRe, () => fallbackResString);
79
79
  return fallbackCallbacks?.length ? require_utils_html.raw("", fallbackCallbacks) : "";
80
80
  }
81
- return require_utils_html.raw(`<template data-hono-target="E:${index}">${fallbackResString}</template><script>
81
+ return require_utils_html.raw(`<template data-hono-target="E:${index}">${fallbackResString}</template><script${nonce ? ` nonce="${nonce}"` : ""}>
82
82
  ((d,c,n) => {
83
83
  c=d.currentScript.previousSibling
84
84
  d=d.getElementById('E:${index}')
@@ -119,7 +119,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
119
119
  buffer[0] += content;
120
120
  return require_utils_html.raw("", content.callbacks);
121
121
  }
122
- return require_utils_html.raw(content + (resolvedCount !== callbacks.length ? "" : `<script>
122
+ return require_utils_html.raw(content + (resolvedCount !== callbacks.length ? "" : `<script${nonce ? ` nonce="${nonce}"` : ""}>
123
123
  ((d,c,n) => {
124
124
  d=d.getElementById('E:${index}')
125
125
  if(!d)return
@@ -6,6 +6,7 @@ const DOM_STASH = Symbol("STASH");
6
6
  const DOM_INTERNAL_TAG = Symbol("INTERNAL");
7
7
  const DOM_MEMO = Symbol("MEMO");
8
8
  const PERMALINK = Symbol("PERMALINK");
9
+ const RENDERED_JSX = Symbol("RENDERED_JSX");
9
10
  //#endregion
10
11
  exports.DOM_ERROR_HANDLER = DOM_ERROR_HANDLER;
11
12
  exports.DOM_INTERNAL_TAG = DOM_INTERNAL_TAG;
@@ -13,3 +14,4 @@ exports.DOM_MEMO = DOM_MEMO;
13
14
  exports.DOM_RENDERER = DOM_RENDERER;
14
15
  exports.DOM_STASH = DOM_STASH;
15
16
  exports.PERMALINK = PERMALINK;
17
+ exports.RENDERED_JSX = RENDERED_JSX;
@@ -1,30 +1,26 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_utils_html = require("../utils/html.js");
3
3
  const require_helper_html_index = require("../helper/html/index.js");
4
+ const require_jsx_constants = require("./constants.js");
4
5
  const require_jsx_utils = require("./utils.js");
5
6
  const require_jsx_base = require("./base.js");
6
7
  const require_jsx_jsx_dev_runtime = require("./jsx-dev-runtime.js");
7
8
  //#region src/jsx/jsx-runtime.ts
9
+ const jsxTemplate = (strings, ...values) => {
10
+ const result = require_helper_html_index.html(strings, ...values);
11
+ return result instanceof Promise ? result.then(require_jsx_base.markRenderedJSX) : require_jsx_base.markRenderedJSX(result);
12
+ };
8
13
  const jsxAttr = (key, v) => {
9
14
  if (!require_jsx_utils.isValidAttributeName(key)) return require_utils_html.raw("");
10
- const buffer = [`${key}="`];
11
- if (key === "style" && typeof v === "object") {
12
- let styleStr = "";
13
- require_jsx_utils.styleObjectForEach(v, (property, value) => {
14
- if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
15
- });
16
- require_utils_html.escapeToBuffer(styleStr, buffer);
17
- buffer[0] += "\"";
18
- } else if (typeof v === "string") {
15
+ if (typeof v === "string") {
16
+ const buffer = [`${key}="`];
19
17
  require_utils_html.escapeToBuffer(v, buffer);
20
- buffer[0] += "\"";
21
- } else if (v === null || v === void 0) return require_utils_html.raw("");
22
- else if (typeof v === "number" || v.isEscaped) buffer[0] += `${v}"`;
23
- else if (v instanceof Promise) buffer.unshift("\"", v);
24
- else {
25
- require_utils_html.escapeToBuffer(v.toString(), buffer);
26
- buffer[0] += "\"";
18
+ return require_utils_html.raw(buffer[0] + "\"");
27
19
  }
20
+ let value = v;
21
+ if (typeof value === "function" && (key === "action" || key === "formaction")) value = require_jsx_constants.PERMALINK in value ? value[require_jsx_constants.PERMALINK] : void 0;
22
+ const buffer = [""];
23
+ require_jsx_base.attributeToBuffer(buffer, "", key, value);
28
24
  return buffer.length === 1 ? require_utils_html.raw(buffer[0]) : require_utils_html.stringBufferToString(buffer, void 0);
29
25
  };
30
26
  const jsxEscape = (value) => value;
@@ -33,5 +29,5 @@ exports.Fragment = require_jsx_base.Fragment;
33
29
  exports.jsx = require_jsx_jsx_dev_runtime.jsxDEV;
34
30
  exports.jsxAttr = jsxAttr;
35
31
  exports.jsxEscape = jsxEscape;
36
- exports.jsxTemplate = require_helper_html_index.html;
32
+ exports.jsxTemplate = jsxTemplate;
37
33
  exports.jsxs = require_jsx_jsx_dev_runtime.jsxDEV;
@@ -17,7 +17,8 @@ const RETAINED_304_HEADERS = [
17
17
  ];
18
18
  const stripWeak = (tag) => tag.replace(/^W\//, "");
19
19
  function etagMatches(etag, ifNoneMatch) {
20
- return ifNoneMatch != null && ifNoneMatch.split(",").some((t) => stripWeak(t.trim()) === stripWeak(etag));
20
+ const expected = stripWeak(etag);
21
+ return ifNoneMatch?.match(/"[^"]*"/g)?.some((tag) => tag === expected) ?? false;
21
22
  }
22
23
  function initializeGenerator(generator) {
23
24
  if (!generator) {
@@ -65,6 +66,7 @@ const etag = (options) => {
65
66
  etag = weak ? `W/"${hash}"` : `"${hash}"`;
66
67
  }
67
68
  if (ifNoneMatch === "*" || etagMatches(etag, ifNoneMatch)) {
69
+ await res.body?.cancel();
68
70
  c.res = new Response(null, {
69
71
  status: 304,
70
72
  statusText: "Not Modified",
@@ -32,6 +32,7 @@ const prettyJSON = (options) => {
32
32
  } catch {
33
33
  return;
34
34
  }
35
+ await c.res.body?.cancel();
35
36
  c.res = new Response(JSON.stringify(obj, null, options?.space ?? 2), c.res);
36
37
  c.res.headers.delete("Content-Length");
37
38
  }
@@ -75,6 +75,7 @@ const timing = (config) => {
75
75
  }
76
76
  };
77
77
  };
78
+ const quote = (s) => `"${s.replace(/[\\"]/g, "\\$&")}"`;
78
79
  /**
79
80
  * Set a metric for the timing middleware.
80
81
  *
@@ -97,11 +98,11 @@ const setMetric = (c, name, valueDescription, description, precision) => {
97
98
  return;
98
99
  }
99
100
  if (typeof valueDescription === "number") {
100
- const dur = valueDescription.toFixed(precision || 1);
101
- const metric = description ? `${name};dur=${dur};desc="${description}"` : `${name};dur=${dur}`;
101
+ const dur = valueDescription.toFixed(precision ?? 1);
102
+ const metric = description ? `${name};dur=${dur};desc=${quote(description)}` : `${name};dur=${dur}`;
102
103
  metrics.headers.push(metric);
103
104
  } else {
104
- const metric = valueDescription ? `${name};desc="${valueDescription}"` : `${name}`;
105
+ const metric = valueDescription ? `${name};desc=${quote(valueDescription)}` : `${name}`;
105
106
  metrics.headers.push(metric);
106
107
  }
107
108
  };
@@ -80,8 +80,8 @@ const parseSigned = async (cookie, secret, name) => {
80
80
  const _serialize = (name, value, opt = {}) => {
81
81
  if (!validCookieNameRegEx.test(name)) throw new Error("Invalid cookie name");
82
82
  let cookie = `${name}=${value}`;
83
- if (name.startsWith("__Secure-") && !opt.secure) throw new Error("__Secure- Cookie must have Secure attributes");
84
- if (name.startsWith("__Host-")) {
83
+ if (/^__secure-/i.test(name) && !opt.secure) throw new Error("__Secure- Cookie must have Secure attributes");
84
+ if (/^__host-/i.test(name)) {
85
85
  if (!opt.secure) throw new Error("__Host- Cookie must have Secure attributes");
86
86
  if (opt.path !== "/") throw new Error("__Host- Cookie must have Path attributes with \"/\"");
87
87
  if (opt.domain) throw new Error("__Host- Cookie must not have Domain attributes");
@@ -10,7 +10,7 @@ const getMimeType = (filename, mimes = baseMimes) => {
10
10
  return mimes[match[1].toLowerCase()];
11
11
  };
12
12
  const getExtension = (mimeType) => {
13
- const baseType = mimeType.split(";", 1)[0].trim();
13
+ const baseType = mimeType.split(";", 1)[0].trim().toLowerCase();
14
14
  for (const ext in baseMimes) {
15
15
  const stored = baseMimes[ext];
16
16
  if (stored === mimeType || stored.split(";", 1)[0].trim() === baseType) return ext;
@@ -162,7 +162,7 @@ const _getQueryParam = (url, key, multiple) => {
162
162
  const hashIndex = url.indexOf("#", 8);
163
163
  if (hashIndex !== -1) url = url.slice(0, hashIndex);
164
164
  let encoded;
165
- if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
165
+ if (!multiple && key && !/[%+&=]/.test(key)) {
166
166
  const queryIndex = url.indexOf("?", 8);
167
167
  let keyIndex = queryIndex;
168
168
  if (keyIndex === -1) return;
@@ -57,7 +57,7 @@ const jsonRegex = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(?:;.+)?$/i;
57
57
  function detectResponseType(response) {
58
58
  const _contentType = response.headers.get("content-type");
59
59
  if (!_contentType) return "text";
60
- const contentType = _contentType.split(";").shift();
60
+ const contentType = _contentType.split(";").shift().trim();
61
61
  if (jsonRegex.test(contentType)) return "json";
62
62
  return "text";
63
63
  }
@@ -19,12 +19,13 @@ const getSpecificity = (type) => {
19
19
  };
20
20
  const defaultMatch = (accepts, config) => {
21
21
  const { supports, default: defaultSupport } = config;
22
+ const exactTypes = new Set(accepts.filter((accept) => getSpecificity(accept.type) === 3).map((accept) => accept.type.toLowerCase()));
22
23
  const sortedAccepts = accepts.filter((accept) => accept.q > 0).sort((a, b) => {
23
24
  if (b.q !== a.q) return b.q - a.q;
24
25
  return getSpecificity(b.type) - getSpecificity(a.type);
25
26
  });
26
27
  for (const accept of sortedAccepts) {
27
- const matched = supports.find((supported) => matchType(accept.type, supported));
28
+ const matched = supports.find((supported) => matchType(accept.type, supported) && (getSpecificity(accept.type) !== 2 || !exactTypes.has(supported.toLowerCase())));
28
29
  if (matched) return matched;
29
30
  }
30
31
  return defaultSupport;
@@ -38,6 +38,8 @@ const defaultExtensionMap = {
38
38
  const determineExtension = (mimeType, userExtensionMap) => {
39
39
  const extensionMap = userExtensionMap || defaultExtensionMap;
40
40
  if (mimeType in extensionMap) return extensionMap[mimeType];
41
+ const lowerCasedMimeType = mimeType.toLowerCase();
42
+ if (lowerCasedMimeType in extensionMap) return extensionMap[lowerCasedMimeType];
41
43
  return getExtension(mimeType) || "html";
42
44
  };
43
45
  const combineBeforeRequestHooks = (hooks) => {
@@ -141,8 +143,7 @@ const fetchRoutesContent = function* (app, beforeRequestHook, afterResponseHook,
141
143
  * `saveContentToFile` is an experimental feature.
142
144
  * The API might be changed.
143
145
  */
144
- const createdDirs = /* @__PURE__ */ new Set();
145
- const saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
146
+ const saveContentToFile = async (data, fsModule, outDir, extensionMap, createdDirs = /* @__PURE__ */ new Set()) => {
146
147
  const awaitedData = await data;
147
148
  if (!awaitedData) return;
148
149
  const { routePath, content, mimeType } = awaitedData;
@@ -182,10 +183,11 @@ const toSSG = async (app, fs, options) => {
182
183
  const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;
183
184
  const combinedBeforeRequestHook = combineBeforeRequestHooks(beforeRequestHooks.length > 0 ? beforeRequestHooks : [(req) => req]);
184
185
  const combinedAfterResponseHook = combineAfterResponseHooks(afterResponseHooks.length > 0 ? afterResponseHooks : [(req) => req]);
186
+ const createdDirs = /* @__PURE__ */ new Set();
185
187
  const getInfoGen = fetchRoutesContent(app, combinedBeforeRequestHook, combinedAfterResponseHook, concurrency);
186
188
  for (const getInfo of getInfoGen) getInfoPromises.push(getInfo.then((getContentGen) => {
187
189
  if (!getContentGen) return;
188
- for (const content of getContentGen) savePromises.push(saveContentToFile(content, fs, outputDir, options?.extensionMap).catch((e) => e));
190
+ for (const content of getContentGen) savePromises.push(saveContentToFile(content, fs, outputDir, options?.extensionMap, createdDirs).catch((e) => e));
189
191
  }));
190
192
  await Promise.all(getInfoPromises);
191
193
  const files = [];
@@ -1,5 +1,5 @@
1
1
  import { escapeToBuffer, raw, resolveCallbackSync, stringBufferToString } from "../utils/html.js";
2
- import { DOM_MEMO, DOM_RENDERER } from "./constants.js";
2
+ import { DOM_MEMO, DOM_RENDERER, RENDERED_JSX } from "./constants.js";
3
3
  import { captureRenderContext, createContext, globalContexts, runWithRenderContext, useContext } from "./context.js";
4
4
  import { domRenderers } from "./intrinsic-element/common.js";
5
5
  import { components_exports } from "./intrinsic-element/components.js";
@@ -25,7 +25,7 @@ const emptyTags = [
25
25
  "track",
26
26
  "wbr"
27
27
  ];
28
- const booleanAttributes = [
28
+ const booleanAttributes = /* @__PURE__ */ new Set([
29
29
  "allowfullscreen",
30
30
  "async",
31
31
  "autofocus",
@@ -51,8 +51,11 @@ const booleanAttributes = [
51
51
  "readonly",
52
52
  "required",
53
53
  "reversed",
54
- "selected"
55
- ];
54
+ "selected",
55
+ "shadowrootclonable",
56
+ "shadowrootdelegatesfocus",
57
+ "shadowrootserializable"
58
+ ]);
56
59
  const resolveFunctionComponentResult = (result, suspendedContext) => result.then((resolved) => {
57
60
  if (typeof resolved !== "string" && !Array.isArray(resolved) && !(resolved instanceof JSXNode)) return resolved;
58
61
  const children = Array.isArray(resolved) ? resolved : [resolved];
@@ -63,6 +66,44 @@ const resolveFunctionComponentResult = (result, suspendedContext) => result.then
63
66
  };
64
67
  return suspendedContext ? suspendedContext(render) : runWithRenderContext(render);
65
68
  });
69
+ const markRenderedJSX = (value) => {
70
+ value[RENDERED_JSX] = true;
71
+ return value;
72
+ };
73
+ const isEscapedAttribute = (value) => value instanceof String && value.isEscaped && !(RENDERED_JSX in value);
74
+ const objectToAttributeString = (v) => {
75
+ const s = v.toString();
76
+ return s instanceof Promise ? s.then(String) : String(s);
77
+ };
78
+ const attributeToBuffer = (buffer, prefix, key, v, tag) => {
79
+ if (key === "ref" || v === null || v === void 0) return;
80
+ if (typeof v === "boolean" && booleanAttributes.has(key)) {
81
+ if (v) buffer[0] += `${prefix}${key}=""`;
82
+ return;
83
+ }
84
+ if (typeof v === "function") {
85
+ if (!key.startsWith("on")) throw new Error(`Invalid prop '${key}' of type 'function' supplied to ${tag ? `'${tag}'` : "a JSX element"}.`);
86
+ return;
87
+ }
88
+ buffer[0] += `${prefix}${key}="`;
89
+ if (key === "style" && typeof v === "object") {
90
+ let styleStr = "";
91
+ styleObjectForEach(v, (property, value) => {
92
+ if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
93
+ });
94
+ escapeToBuffer(styleStr, buffer);
95
+ } else if (typeof v === "string") escapeToBuffer(v, buffer);
96
+ else if (typeof v === "number" || isEscapedAttribute(v)) buffer[0] += `${v}`;
97
+ else {
98
+ const s = v instanceof Promise ? v.then((r) => typeof r === "object" && r !== null && !isEscapedAttribute(r) ? objectToAttributeString(r) : r) : objectToAttributeString(v);
99
+ if (s instanceof Promise) {
100
+ buffer.unshift("\"", s);
101
+ return;
102
+ }
103
+ escapeToBuffer(s, buffer);
104
+ }
105
+ buffer[0] += "\"";
106
+ };
66
107
  const childrenToStringToBuffer = (children, buffer) => {
67
108
  for (let i = 0, len = children.length; i < len; i++) {
68
109
  const child = children[i];
@@ -114,7 +155,7 @@ var JSXNode = class {
114
155
  const render = () => {
115
156
  const buffer = [""];
116
157
  this.toStringToBuffer(buffer);
117
- return buffer.length === 1 ? "callbacks" in buffer ? resolveCallbackSync(raw(buffer[0], buffer.callbacks)).toString() : buffer[0] : stringBufferToString(buffer, buffer.callbacks);
158
+ return buffer.length === 1 ? "callbacks" in buffer ? resolveCallbackSync(raw(buffer[0], buffer.callbacks)).toString() : buffer[0] : stringBufferToString(buffer, buffer.callbacks).then(markRenderedJSX);
118
159
  };
119
160
  return runWithRenderContext(render);
120
161
  }
@@ -127,34 +168,10 @@ var JSXNode = class {
127
168
  for (let [key, v] of Object.entries(props)) {
128
169
  key = normalizeKey(key);
129
170
  if (!isValidAttributeName(key)) continue;
130
- if (key === "children") {} else if (key === "style" && typeof v === "object") {
131
- let styleStr = "";
132
- styleObjectForEach(v, (property, value) => {
133
- if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
134
- });
135
- buffer[0] += " style=\"";
136
- escapeToBuffer(styleStr, buffer);
137
- buffer[0] += "\"";
138
- } else if (typeof v === "string") {
139
- buffer[0] += ` ${key}="`;
140
- escapeToBuffer(v, buffer);
141
- buffer[0] += "\"";
142
- } else if (v === null || v === void 0) {} else if (typeof v === "number" || v.isEscaped) buffer[0] += ` ${key}="${v}"`;
143
- else if (typeof v === "boolean" && booleanAttributes.includes(key)) {
144
- if (v) buffer[0] += ` ${key}=""`;
145
- } else if (key === "dangerouslySetInnerHTML") {
171
+ if (key === "children") {} else if (key === "dangerouslySetInnerHTML" && typeof v === "object" && v !== null && "__html" in v) {
146
172
  if (children.length > 0) throw new Error("Can only set one of `children` or `props.dangerouslySetInnerHTML`.");
147
173
  children = [raw(v.__html)];
148
- } else if (v instanceof Promise) {
149
- buffer[0] += ` ${key}="`;
150
- buffer.unshift("\"", v);
151
- } else if (typeof v === "function") {
152
- if (!key.startsWith("on") && key !== "ref") throw new Error(`Invalid prop '${key}' of type 'function' supplied to '${tag}'.`);
153
- } else {
154
- buffer[0] += ` ${key}="`;
155
- escapeToBuffer(v.toString(), buffer);
156
- buffer[0] += "\"";
157
- }
174
+ } else attributeToBuffer(buffer, " ", key, v, tag);
158
175
  }
159
176
  if (emptyTags.includes(tag) && children.length === 0) {
160
177
  buffer[0] += "/>";
@@ -248,4 +265,4 @@ const cloneElement = (element, props, ...children) => {
248
265
  };
249
266
  const reactAPICompatVersion = "19.0.0-hono-jsx";
250
267
  //#endregion
251
- export { Fragment, JSXFragmentNode, JSXNode, booleanAttributes, cloneElement, getNameSpaceContext, isUntrustedObject, isValidElement, jsx, jsxFn, memo, reactAPICompatVersion, renderChildren, renderUntrustedObject, shallowEqual };
268
+ export { Fragment, JSXFragmentNode, JSXNode, attributeToBuffer, booleanAttributes, cloneElement, getNameSpaceContext, isUntrustedObject, isValidElement, jsx, jsxFn, markRenderedJSX, memo, reactAPICompatVersion, renderChildren, renderUntrustedObject, shallowEqual };
@@ -77,7 +77,7 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
77
77
  buffer[0] = buffer[0].replace(replaceRe, () => fallbackResString);
78
78
  return fallbackCallbacks?.length ? raw("", fallbackCallbacks) : "";
79
79
  }
80
- return raw(`<template data-hono-target="E:${index}">${fallbackResString}</template><script>
80
+ return raw(`<template data-hono-target="E:${index}">${fallbackResString}</template><script${nonce ? ` nonce="${nonce}"` : ""}>
81
81
  ((d,c,n) => {
82
82
  c=d.currentScript.previousSibling
83
83
  d=d.getElementById('E:${index}')
@@ -118,7 +118,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
118
118
  buffer[0] += content;
119
119
  return raw("", content.callbacks);
120
120
  }
121
- return raw(content + (resolvedCount !== callbacks.length ? "" : `<script>
121
+ return raw(content + (resolvedCount !== callbacks.length ? "" : `<script${nonce ? ` nonce="${nonce}"` : ""}>
122
122
  ((d,c,n) => {
123
123
  d=d.getElementById('E:${index}')
124
124
  if(!d)return
@@ -5,5 +5,6 @@ const DOM_STASH = Symbol("STASH");
5
5
  const DOM_INTERNAL_TAG = Symbol("INTERNAL");
6
6
  const DOM_MEMO = Symbol("MEMO");
7
7
  const PERMALINK = Symbol("PERMALINK");
8
+ const RENDERED_JSX = Symbol("RENDERED_JSX");
8
9
  //#endregion
9
- export { DOM_ERROR_HANDLER, DOM_INTERNAL_TAG, DOM_MEMO, DOM_RENDERER, DOM_STASH, PERMALINK };
10
+ export { DOM_ERROR_HANDLER, DOM_INTERNAL_TAG, DOM_MEMO, DOM_RENDERER, DOM_STASH, PERMALINK, RENDERED_JSX };
@@ -1,31 +1,27 @@
1
1
  import { escapeToBuffer, raw, stringBufferToString } from "../utils/html.js";
2
2
  import { html } from "../helper/html/index.js";
3
- import { isValidAttributeName, styleObjectForEach } from "./utils.js";
4
- import { Fragment } from "./base.js";
3
+ import { PERMALINK } from "./constants.js";
4
+ import { isValidAttributeName } from "./utils.js";
5
+ import { Fragment, attributeToBuffer, markRenderedJSX } from "./base.js";
5
6
  import { jsxDEV } from "./jsx-dev-runtime.js";
6
7
  //#region src/jsx/jsx-runtime.ts
8
+ const jsxTemplate = (strings, ...values) => {
9
+ const result = html(strings, ...values);
10
+ return result instanceof Promise ? result.then(markRenderedJSX) : markRenderedJSX(result);
11
+ };
7
12
  const jsxAttr = (key, v) => {
8
13
  if (!isValidAttributeName(key)) return raw("");
9
- const buffer = [`${key}="`];
10
- if (key === "style" && typeof v === "object") {
11
- let styleStr = "";
12
- styleObjectForEach(v, (property, value) => {
13
- if (value != null) styleStr += `${styleStr ? ";" : ""}${property}:${value}`;
14
- });
15
- escapeToBuffer(styleStr, buffer);
16
- buffer[0] += "\"";
17
- } else if (typeof v === "string") {
14
+ if (typeof v === "string") {
15
+ const buffer = [`${key}="`];
18
16
  escapeToBuffer(v, buffer);
19
- buffer[0] += "\"";
20
- } else if (v === null || v === void 0) return raw("");
21
- else if (typeof v === "number" || v.isEscaped) buffer[0] += `${v}"`;
22
- else if (v instanceof Promise) buffer.unshift("\"", v);
23
- else {
24
- escapeToBuffer(v.toString(), buffer);
25
- buffer[0] += "\"";
17
+ return raw(buffer[0] + "\"");
26
18
  }
19
+ let value = v;
20
+ if (typeof value === "function" && (key === "action" || key === "formaction")) value = PERMALINK in value ? value[PERMALINK] : void 0;
21
+ const buffer = [""];
22
+ attributeToBuffer(buffer, "", key, value);
27
23
  return buffer.length === 1 ? raw(buffer[0]) : stringBufferToString(buffer, void 0);
28
24
  };
29
25
  const jsxEscape = (value) => value;
30
26
  //#endregion
31
- export { Fragment, jsxDEV as jsx, jsxAttr, jsxEscape, html as jsxTemplate, jsxDEV as jsxs };
27
+ export { Fragment, jsxDEV as jsx, jsxAttr, jsxEscape, jsxTemplate, jsxDEV as jsxs };
@@ -16,7 +16,8 @@ const RETAINED_304_HEADERS = [
16
16
  ];
17
17
  const stripWeak = (tag) => tag.replace(/^W\//, "");
18
18
  function etagMatches(etag, ifNoneMatch) {
19
- return ifNoneMatch != null && ifNoneMatch.split(",").some((t) => stripWeak(t.trim()) === stripWeak(etag));
19
+ const expected = stripWeak(etag);
20
+ return ifNoneMatch?.match(/"[^"]*"/g)?.some((tag) => tag === expected) ?? false;
20
21
  }
21
22
  function initializeGenerator(generator) {
22
23
  if (!generator) {
@@ -64,6 +65,7 @@ const etag = (options) => {
64
65
  etag = weak ? `W/"${hash}"` : `"${hash}"`;
65
66
  }
66
67
  if (ifNoneMatch === "*" || etagMatches(etag, ifNoneMatch)) {
68
+ await res.body?.cancel();
67
69
  c.res = new Response(null, {
68
70
  status: 304,
69
71
  statusText: "Not Modified",
@@ -1,5 +1,5 @@
1
- import { parseAccept } from "../../utils/accept.js";
2
1
  import { getCookie, setCookie } from "../../helper/cookie/index.js";
2
+ import { parseAccept } from "../../utils/accept.js";
3
3
  //#region src/middleware/language/language.ts
4
4
  const DEFAULT_OPTIONS = {
5
5
  order: [
@@ -31,6 +31,7 @@ const prettyJSON = (options) => {
31
31
  } catch {
32
32
  return;
33
33
  }
34
+ await c.res.body?.cancel();
34
35
  c.res = new Response(JSON.stringify(obj, null, options?.space ?? 2), c.res);
35
36
  c.res.headers.delete("Content-Length");
36
37
  }
@@ -74,6 +74,7 @@ const timing = (config) => {
74
74
  }
75
75
  };
76
76
  };
77
+ const quote = (s) => `"${s.replace(/[\\"]/g, "\\$&")}"`;
77
78
  /**
78
79
  * Set a metric for the timing middleware.
79
80
  *
@@ -96,11 +97,11 @@ const setMetric = (c, name, valueDescription, description, precision) => {
96
97
  return;
97
98
  }
98
99
  if (typeof valueDescription === "number") {
99
- const dur = valueDescription.toFixed(precision || 1);
100
- const metric = description ? `${name};dur=${dur};desc="${description}"` : `${name};dur=${dur}`;
100
+ const dur = valueDescription.toFixed(precision ?? 1);
101
+ const metric = description ? `${name};dur=${dur};desc=${quote(description)}` : `${name};dur=${dur}`;
101
102
  metrics.headers.push(metric);
102
103
  } else {
103
- const metric = valueDescription ? `${name};desc="${valueDescription}"` : `${name}`;
104
+ const metric = valueDescription ? `${name};desc=${quote(valueDescription)}` : `${name}`;
104
105
  metrics.headers.push(metric);
105
106
  }
106
107
  };
@@ -79,8 +79,8 @@ const parseSigned = async (cookie, secret, name) => {
79
79
  const _serialize = (name, value, opt = {}) => {
80
80
  if (!validCookieNameRegEx.test(name)) throw new Error("Invalid cookie name");
81
81
  let cookie = `${name}=${value}`;
82
- if (name.startsWith("__Secure-") && !opt.secure) throw new Error("__Secure- Cookie must have Secure attributes");
83
- if (name.startsWith("__Host-")) {
82
+ if (/^__secure-/i.test(name) && !opt.secure) throw new Error("__Secure- Cookie must have Secure attributes");
83
+ if (/^__host-/i.test(name)) {
84
84
  if (!opt.secure) throw new Error("__Host- Cookie must have Secure attributes");
85
85
  if (opt.path !== "/") throw new Error("__Host- Cookie must have Path attributes with \"/\"");
86
86
  if (opt.domain) throw new Error("__Host- Cookie must not have Domain attributes");
@@ -9,7 +9,7 @@ const getMimeType = (filename, mimes = baseMimes) => {
9
9
  return mimes[match[1].toLowerCase()];
10
10
  };
11
11
  const getExtension = (mimeType) => {
12
- const baseType = mimeType.split(";", 1)[0].trim();
12
+ const baseType = mimeType.split(";", 1)[0].trim().toLowerCase();
13
13
  for (const ext in baseMimes) {
14
14
  const stored = baseMimes[ext];
15
15
  if (stored === mimeType || stored.split(";", 1)[0].trim() === baseType) return ext;