@depup/hono 4.13.4-depup.0 → 4.13.7-depup.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.
- package/README.md +2 -2
- package/changes.json +1 -1
- package/dist/cjs/client/client.js +4 -4
- package/dist/cjs/helper/ssg/ssg.js +1 -1
- package/dist/cjs/helper/ssg/utils.js +30 -10
- package/dist/cjs/hono-base.js +7 -6
- package/dist/cjs/jsx/base.js +18 -1
- package/dist/cjs/jsx/components.js +25 -26
- package/dist/cjs/jsx/context.js +5 -5
- package/dist/cjs/jsx/dom/server.js +5 -1
- package/dist/cjs/jsx/intrinsic-element/components.js +2 -2
- package/dist/cjs/jsx/streaming.js +4 -5
- package/dist/cjs/middleware/cache/index.js +1 -1
- package/dist/cjs/utils/body.js +15 -3
- package/dist/cjs/utils/url.js +9 -1
- package/dist/client/client.js +4 -4
- package/dist/helper/ssg/ssg.js +1 -1
- package/dist/helper/ssg/utils.js +30 -10
- package/dist/hono-base.js +7 -6
- package/dist/jsx/base.js +15 -1
- package/dist/jsx/components.js +26 -27
- package/dist/jsx/context.js +6 -6
- package/dist/jsx/dom/server.js +5 -1
- package/dist/jsx/intrinsic-element/components.js +3 -3
- package/dist/jsx/streaming.js +5 -6
- package/dist/middleware/cache/index.js +1 -1
- package/dist/types/context.d.ts +2 -2
- package/dist/types/jsx/base.d.ts +3 -0
- package/dist/types/utils/url.d.ts +4 -0
- package/dist/utils/body.js +15 -3
- package/dist/utils/url.js +9 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -13,8 +13,8 @@ npm install @depup/hono
|
|
|
13
13
|
|
|
14
14
|
| Field | Value |
|
|
15
15
|
|-------|-------|
|
|
16
|
-
| Original | [hono](https://www.npmjs.com/package/hono) @ 4.13.
|
|
17
|
-
| Processed | 2026-
|
|
16
|
+
| Original | [hono](https://www.npmjs.com/package/hono) @ 4.13.7 |
|
|
17
|
+
| Processed | 2026-09-05 |
|
|
18
18
|
| Smoke test | passed |
|
|
19
19
|
| Deps updated | 0 |
|
|
20
20
|
|
package/changes.json
CHANGED
|
@@ -157,24 +157,24 @@ const hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
|
|
|
157
157
|
const path = parts.join("/");
|
|
158
158
|
const url = (0, import_utils.mergePath)(baseUrl, path);
|
|
159
159
|
if (method === "url" || method === "path") {
|
|
160
|
-
let result = url;
|
|
160
|
+
let result = (0, import_utils.removeIndexString)(url);
|
|
161
161
|
if (opts.args[0]) {
|
|
162
162
|
if (opts.args[0].param) {
|
|
163
|
-
result = (0, import_utils.replaceUrlParam)(
|
|
163
|
+
result = (0, import_utils.replaceUrlParam)(result, opts.args[0].param);
|
|
164
164
|
}
|
|
165
165
|
if (opts.args[0].query) {
|
|
166
166
|
result = appendQueryParams(result, buildSearchParamsOption(opts.args[0].query));
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
result = (0, import_utils.removeIndexString)(result);
|
|
170
169
|
if (method === "url") {
|
|
171
170
|
return new URL(result);
|
|
172
171
|
}
|
|
173
172
|
return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
|
|
174
173
|
}
|
|
175
174
|
if (method === "ws") {
|
|
175
|
+
const normalizedUrl = (0, import_utils.removeIndexString)(url);
|
|
176
176
|
const webSocketUrl = (0, import_utils.replaceUrlProtocol)(
|
|
177
|
-
opts.args[0]?.param ? (0, import_utils.replaceUrlParam)(
|
|
177
|
+
opts.args[0]?.param ? (0, import_utils.replaceUrlParam)(normalizedUrl, opts.args[0].param) : normalizedUrl,
|
|
178
178
|
"ws"
|
|
179
179
|
);
|
|
180
180
|
const targetUrl = new URL(webSocketUrl);
|
|
@@ -206,7 +206,7 @@ const saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
|
|
|
206
206
|
const { routePath, content, mimeType } = awaitedData;
|
|
207
207
|
const filePath = generateFilePath(routePath, outDir, mimeType, extensionMap);
|
|
208
208
|
const dirPath = (0, import_utils2.dirname)(filePath);
|
|
209
|
-
if (!createdDirs.has(dirPath)) {
|
|
209
|
+
if (dirPath !== "" && !createdDirs.has(dirPath)) {
|
|
210
210
|
await fsModule.mkdir(dirPath, { recursive: true });
|
|
211
211
|
createdDirs.add(dirPath);
|
|
212
212
|
}
|
|
@@ -33,8 +33,14 @@ const dirname = (path) => {
|
|
|
33
33
|
const normalizePath = (path) => {
|
|
34
34
|
return path.replace(/(\\)/g, "/").replace(/\/$/g, "");
|
|
35
35
|
};
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const getUncRoot = (path) => {
|
|
37
|
+
const uncRoot = path.replace(/\\/g, "/").match(/^\/\/([^/]+)\/([^/]+)/);
|
|
38
|
+
if (uncRoot) {
|
|
39
|
+
return `${uncRoot[1].toLowerCase()}/${uncRoot[2].toLowerCase()}`;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const handleParent = (resultPaths) => {
|
|
43
|
+
if (resultPaths.length === 0 || resultPaths[resultPaths.length - 1] === "..") {
|
|
38
44
|
resultPaths.push("..");
|
|
39
45
|
} else {
|
|
40
46
|
resultPaths.pop();
|
|
@@ -47,22 +53,20 @@ const handleNonDot = (path, resultPaths) => {
|
|
|
47
53
|
}
|
|
48
54
|
};
|
|
49
55
|
const handleSegments = (paths, resultPaths) => {
|
|
50
|
-
let beforeParentFlag = false;
|
|
51
56
|
for (const path of paths) {
|
|
52
57
|
if (path === "..") {
|
|
53
|
-
handleParent(resultPaths
|
|
54
|
-
beforeParentFlag = true;
|
|
58
|
+
handleParent(resultPaths);
|
|
55
59
|
} else {
|
|
56
60
|
handleNonDot(path, resultPaths);
|
|
57
|
-
beforeParentFlag = false;
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
};
|
|
61
64
|
const joinPaths = (...paths) => {
|
|
65
|
+
const hasUncPrefix = getUncRoot(paths[0]) !== void 0;
|
|
62
66
|
paths = paths.map(normalizePath);
|
|
63
67
|
const resultPaths = [];
|
|
64
68
|
handleSegments(paths.join("/").split("/"), resultPaths);
|
|
65
|
-
return (paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
|
|
69
|
+
return (hasUncPrefix ? "//" : paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
|
|
66
70
|
};
|
|
67
71
|
const filterStaticGenerateRoutes = (hono) => {
|
|
68
72
|
return hono.routes.reduce((acc, { method, handler, path }) => {
|
|
@@ -76,10 +80,26 @@ const filterStaticGenerateRoutes = (hono) => {
|
|
|
76
80
|
const isDynamicRoute = (path) => {
|
|
77
81
|
return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*"));
|
|
78
82
|
};
|
|
83
|
+
const toSegments = (path) => path === "" ? [] : path.split("/");
|
|
84
|
+
const getPathRoot = (path) => {
|
|
85
|
+
const normalizedPath = path.replace(/\\/g, "/");
|
|
86
|
+
const uncRoot = getUncRoot(normalizedPath);
|
|
87
|
+
if (uncRoot) {
|
|
88
|
+
return `unc:${uncRoot}`;
|
|
89
|
+
}
|
|
90
|
+
const driveRoot = normalizedPath.match(/^([A-Za-z]):/);
|
|
91
|
+
if (driveRoot) {
|
|
92
|
+
const kind = normalizedPath[2] === "/" ? "drive-absolute" : "drive-relative";
|
|
93
|
+
return `${kind}:${driveRoot[1].toLowerCase()}`;
|
|
94
|
+
}
|
|
95
|
+
return normalizedPath.startsWith("/") ? "absolute" : "relative";
|
|
96
|
+
};
|
|
79
97
|
const ensureWithinOutDir = (outDir, filePath) => {
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
|
|
98
|
+
const outDirSegments = toSegments(joinPaths(outDir));
|
|
99
|
+
const filePathSegments = toSegments(joinPaths(filePath));
|
|
100
|
+
const hasMismatchedPathRoot = getPathRoot(outDir) !== getPathRoot(filePath);
|
|
101
|
+
const climbsAboveOutDir = filePathSegments[outDirSegments.length] === "..";
|
|
102
|
+
if (hasMismatchedPathRoot || filePathSegments.length <= outDirSegments.length || !outDirSegments.every((segment, i) => segment === filePathSegments[i]) || climbsAboveOutDir) {
|
|
83
103
|
throw new Error(`Path traversal detected: "${filePath}" is outside the output directory`);
|
|
84
104
|
}
|
|
85
105
|
};
|
package/dist/cjs/hono-base.js
CHANGED
|
@@ -61,13 +61,14 @@ class Hono {
|
|
|
61
61
|
const allMethods = [...import_router.METHODS, import_router.METHOD_NAME_ALL_LOWERCASE];
|
|
62
62
|
allMethods.forEach((method) => {
|
|
63
63
|
this[method] = (args1, ...args) => {
|
|
64
|
+
const methodName = method.toUpperCase();
|
|
64
65
|
if (typeof args1 === "string") {
|
|
65
66
|
this.#path = args1;
|
|
66
67
|
} else {
|
|
67
|
-
this.#addRoute(
|
|
68
|
+
this.#addRoute(methodName, this.#path, args1);
|
|
68
69
|
}
|
|
69
70
|
args.forEach((handler) => {
|
|
70
|
-
this.#addRoute(
|
|
71
|
+
this.#addRoute(methodName, this.#path, handler);
|
|
71
72
|
});
|
|
72
73
|
return this;
|
|
73
74
|
};
|
|
@@ -76,9 +77,10 @@ class Hono {
|
|
|
76
77
|
for (const p of [path].flat()) {
|
|
77
78
|
this.#path = p;
|
|
78
79
|
for (const m of [method].flat()) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
const methodName = m.toUpperCase();
|
|
81
|
+
for (const handler of handlers) {
|
|
82
|
+
this.#addRoute(methodName, this.#path, handler);
|
|
83
|
+
}
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
return this;
|
|
@@ -279,7 +281,6 @@ class Hono {
|
|
|
279
281
|
return this;
|
|
280
282
|
}
|
|
281
283
|
#addRoute(method, path, handler, baseRoutePath) {
|
|
282
|
-
method = method.toUpperCase();
|
|
283
284
|
path = (0, import_url.mergePath)(this._basePath, path);
|
|
284
285
|
const r = {
|
|
285
286
|
basePath: baseRoutePath !== void 0 ? (0, import_url.mergePath)(this._basePath, baseRoutePath) : this._basePath,
|
package/dist/cjs/jsx/base.js
CHANGED
|
@@ -33,11 +33,14 @@ __export(base_exports, {
|
|
|
33
33
|
booleanAttributes: () => booleanAttributes,
|
|
34
34
|
cloneElement: () => cloneElement,
|
|
35
35
|
getNameSpaceContext: () => getNameSpaceContext,
|
|
36
|
+
isUntrustedObject: () => isUntrustedObject,
|
|
36
37
|
isValidElement: () => isValidElement,
|
|
37
38
|
jsx: () => jsx,
|
|
38
39
|
jsxFn: () => jsxFn,
|
|
39
40
|
memo: () => memo,
|
|
40
41
|
reactAPICompatVersion: () => reactAPICompatVersion,
|
|
42
|
+
renderChildren: () => renderChildren,
|
|
43
|
+
renderUntrustedObject: () => renderUntrustedObject,
|
|
41
44
|
shallowEqual: () => shallowEqual
|
|
42
45
|
});
|
|
43
46
|
module.exports = __toCommonJS(base_exports);
|
|
@@ -101,7 +104,7 @@ const booleanAttributes = [
|
|
|
101
104
|
"selected"
|
|
102
105
|
];
|
|
103
106
|
const resolveFunctionComponentResult = (result, suspendedContext) => result.then((resolved) => {
|
|
104
|
-
if (!Array.isArray(resolved) && !(resolved instanceof JSXNode)) {
|
|
107
|
+
if (typeof resolved !== "string" && !Array.isArray(resolved) && !(resolved instanceof JSXNode)) {
|
|
105
108
|
return resolved;
|
|
106
109
|
}
|
|
107
110
|
const children = Array.isArray(resolved) ? resolved : [resolved];
|
|
@@ -139,6 +142,17 @@ const childrenToStringToBuffer = (children, buffer) => {
|
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
};
|
|
145
|
+
const renderChildren = (children) => (0, import_context.runWithRenderContext)(() => {
|
|
146
|
+
const buffer = [""];
|
|
147
|
+
childrenToStringToBuffer(children, buffer);
|
|
148
|
+
return buffer.length === 1 ? (0, import_html.raw)(buffer[0], buffer.callbacks) : (0, import_html2.stringBufferToString)(buffer, buffer.callbacks);
|
|
149
|
+
});
|
|
150
|
+
const isUntrustedObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof JSXNode) && !(value instanceof Promise) && !value.isEscaped && typeof value.toString === "function";
|
|
151
|
+
const renderUntrustedObject = (value) => {
|
|
152
|
+
const stringified = value.toString();
|
|
153
|
+
const escape = (result) => renderChildren([String(result)]);
|
|
154
|
+
return stringified instanceof Promise ? stringified.then(escape) : escape(stringified);
|
|
155
|
+
};
|
|
142
156
|
class JSXNode {
|
|
143
157
|
tag;
|
|
144
158
|
props;
|
|
@@ -369,10 +383,13 @@ const reactAPICompatVersion = "19.0.0-hono-jsx";
|
|
|
369
383
|
booleanAttributes,
|
|
370
384
|
cloneElement,
|
|
371
385
|
getNameSpaceContext,
|
|
386
|
+
isUntrustedObject,
|
|
372
387
|
isValidElement,
|
|
373
388
|
jsx,
|
|
374
389
|
jsxFn,
|
|
375
390
|
memo,
|
|
376
391
|
reactAPICompatVersion,
|
|
392
|
+
renderChildren,
|
|
393
|
+
renderUntrustedObject,
|
|
377
394
|
shallowEqual
|
|
378
395
|
});
|
|
@@ -31,7 +31,7 @@ var import_streaming = require("./streaming");
|
|
|
31
31
|
let errorBoundaryCounter = 0;
|
|
32
32
|
const childrenToString = async (children) => {
|
|
33
33
|
try {
|
|
34
|
-
return children.flat().map(
|
|
34
|
+
return children.flat().map(resolveChildEarly);
|
|
35
35
|
} catch (e) {
|
|
36
36
|
if (e instanceof Promise) {
|
|
37
37
|
const resume = (0, import_context.captureRenderContext)();
|
|
@@ -42,18 +42,16 @@ const childrenToString = async (children) => {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
const resolveChildEarly = (
|
|
46
|
-
if (
|
|
45
|
+
const resolveChildEarly = (child) => {
|
|
46
|
+
if (child == null || typeof child === "boolean") {
|
|
47
47
|
return "";
|
|
48
|
-
} else if (typeof
|
|
49
|
-
return
|
|
48
|
+
} else if (typeof child === "string" || Array.isArray(child)) {
|
|
49
|
+
return (0, import_base.renderChildren)([child]);
|
|
50
|
+
} else if ((0, import_base.isUntrustedObject)(child)) {
|
|
51
|
+
return (0, import_base.renderUntrustedObject)(child);
|
|
50
52
|
} else {
|
|
51
|
-
const str =
|
|
52
|
-
|
|
53
|
-
return (0, import_html.raw)(str);
|
|
54
|
-
} else {
|
|
55
|
-
return str;
|
|
56
|
-
}
|
|
53
|
+
const str = child.toString();
|
|
54
|
+
return str instanceof Promise ? str : (0, import_html.raw)(str);
|
|
57
55
|
}
|
|
58
56
|
};
|
|
59
57
|
const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
|
|
@@ -69,26 +67,27 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
|
|
|
69
67
|
let fallbackStrPromise;
|
|
70
68
|
const resolveFallbackStr = () => fallbackStrPromise ||= (async () => {
|
|
71
69
|
const awaitedFallback = await fallback;
|
|
72
|
-
if (
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
81
|
-
}
|
|
70
|
+
if (awaitedFallback === null || awaitedFallback === void 0) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (typeof awaitedFallback === "string" || Array.isArray(awaitedFallback)) {
|
|
74
|
+
return getResume()(() => (0, import_base.renderChildren)([awaitedFallback]));
|
|
75
|
+
}
|
|
76
|
+
if ((0, import_base.isUntrustedObject)(awaitedFallback)) {
|
|
77
|
+
return getResume()(() => (0, import_base.renderUntrustedObject)(awaitedFallback));
|
|
82
78
|
}
|
|
79
|
+
const fallbackResult = await getResume()(() => awaitedFallback.toString());
|
|
80
|
+
return (0, import_html.raw)(
|
|
81
|
+
fallbackResult,
|
|
82
|
+
fallbackResult.callbacks || awaitedFallback.callbacks
|
|
83
|
+
);
|
|
83
84
|
})();
|
|
84
85
|
const renderFallback = async (error) => {
|
|
85
86
|
const fallbackStr = await resolveFallbackStr();
|
|
86
87
|
return getResume()(async () => {
|
|
87
88
|
onError?.(error);
|
|
88
89
|
const fallbackRes = fallbackStr !== void 0 ? fallbackStr : fallbackRender && (0, import_base.jsx)(import_base.Fragment, {}, fallbackRender(error)) || "";
|
|
89
|
-
const fallbackResString = await (0, import_base.Fragment)({
|
|
90
|
-
children: fallbackRes
|
|
91
|
-
}).toString();
|
|
90
|
+
const fallbackResString = await (0, import_base.Fragment)({ children: fallbackRes }).toString();
|
|
92
91
|
return (0, import_html.raw)(
|
|
93
92
|
fallbackResString,
|
|
94
93
|
fallbackResString.callbacks || fallbackRes.callbacks
|
|
@@ -121,7 +120,7 @@ const ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) =>
|
|
|
121
120
|
const fallbackResString = await renderFallback(error2);
|
|
122
121
|
const fallbackCallbacks = fallbackResString.callbacks;
|
|
123
122
|
if (buffer) {
|
|
124
|
-
buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
|
|
123
|
+
buffer[0] = buffer[0].replace(replaceRe, () => fallbackResString);
|
|
125
124
|
return fallbackCallbacks?.length ? (0, import_html.raw)("", fallbackCallbacks) : "";
|
|
126
125
|
}
|
|
127
126
|
return (0, import_html.raw)(
|
|
@@ -160,7 +159,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
|
|
|
160
159
|
</script>`;
|
|
161
160
|
if (htmlArray.every((html2) => !html2.callbacks?.length)) {
|
|
162
161
|
if (buffer) {
|
|
163
|
-
buffer[0] = buffer[0].replace(replaceRe, content);
|
|
162
|
+
buffer[0] = buffer[0].replace(replaceRe, () => content);
|
|
164
163
|
}
|
|
165
164
|
return html;
|
|
166
165
|
}
|
package/dist/cjs/jsx/context.js
CHANGED
|
@@ -155,18 +155,18 @@ const createContext = (defaultValue) => {
|
|
|
155
155
|
const context = ((props) => {
|
|
156
156
|
const contextValues = getContextValuesIn(getCurrentStore(), context);
|
|
157
157
|
contextValues.push(props.value);
|
|
158
|
-
let
|
|
158
|
+
let rendered;
|
|
159
159
|
try {
|
|
160
|
-
|
|
160
|
+
rendered = typeof props.children === "string" ? (0, import_base.renderChildren)([props.children]) : (0, import_base.isUntrustedObject)(props.children) ? (0, import_base.renderUntrustedObject)(props.children) : props.children ? (Array.isArray(props.children) ? new import_base.JSXFragmentNode("", {}, props.children) : props.children).toString() : (0, import_html.raw)("");
|
|
161
161
|
} catch (e) {
|
|
162
162
|
contextValues.pop();
|
|
163
163
|
throw e;
|
|
164
164
|
}
|
|
165
|
-
if (
|
|
166
|
-
return
|
|
165
|
+
if (rendered instanceof Promise) {
|
|
166
|
+
return rendered.finally(() => contextValues.pop()).then((resString) => (0, import_html.raw)(resString, resString.callbacks));
|
|
167
167
|
} else {
|
|
168
168
|
contextValues.pop();
|
|
169
|
-
return (0, import_html.raw)(
|
|
169
|
+
return (0, import_html.raw)(rendered);
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
172
|
context.values = values;
|
|
@@ -33,13 +33,16 @@ __export(server_exports, {
|
|
|
33
33
|
version: () => import__.default
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(server_exports);
|
|
36
|
+
var import_base = require("../base");
|
|
36
37
|
var import_streaming = require("../streaming");
|
|
37
38
|
var import__ = __toESM(require("./"), 1);
|
|
39
|
+
const prepareRoot = (element) => typeof element === "string" || Array.isArray(element) ? (0, import_base.renderChildren)([element]) : element;
|
|
38
40
|
const renderToString = (element, options = {}) => {
|
|
39
41
|
if (Object.keys(options).length > 0) {
|
|
40
42
|
console.warn("options are not supported yet");
|
|
41
43
|
}
|
|
42
|
-
|
|
44
|
+
element = prepareRoot(element);
|
|
45
|
+
const res = element instanceof Promise ? element : element?.toString() ?? "";
|
|
43
46
|
if (typeof res !== "string") {
|
|
44
47
|
throw new Error("Async component is not supported in renderToString");
|
|
45
48
|
}
|
|
@@ -49,6 +52,7 @@ const renderToReadableStream = async (element, options = {}) => {
|
|
|
49
52
|
if (Object.keys(options).some((key) => key !== "onError")) {
|
|
50
53
|
console.warn("options are not supported yet, except onError");
|
|
51
54
|
}
|
|
55
|
+
element = prepareRoot(element);
|
|
52
56
|
if (!element || typeof element !== "object") {
|
|
53
57
|
element = element?.toString() ?? "";
|
|
54
58
|
}
|
|
@@ -85,10 +85,10 @@ const insertIntoHead = (tagName, tag, props, precedence) => ({ buffer, context }
|
|
|
85
85
|
insertTags.forEach((tag2) => {
|
|
86
86
|
buffer[0] = buffer[0].replaceAll(tag2, "");
|
|
87
87
|
});
|
|
88
|
-
buffer[0] = buffer[0].replace(/(?=<\/head>)/, insertTags.join(""));
|
|
88
|
+
buffer[0] = buffer[0].replace(/(?=<\/head>)/, () => insertTags.join(""));
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
|
-
const returnWithoutSpecialBehavior = (tag, children, props) => (0,
|
|
91
|
+
const returnWithoutSpecialBehavior = (tag, children, props) => (0, import_base.renderChildren)([new import_base.JSXNode(tag, props, (0, import_children.toArray)(children ?? []))]);
|
|
92
92
|
const documentMetadataTag = (tag, children, props, sort) => {
|
|
93
93
|
if ("itemProp" in props) {
|
|
94
94
|
return returnWithoutSpecialBehavior(tag, children, props);
|
|
@@ -32,6 +32,7 @@ var import_components2 = require("./dom/components");
|
|
|
32
32
|
var import_render = require("./dom/render");
|
|
33
33
|
const StreamingContext = (0, import_context.createContext)(null);
|
|
34
34
|
let suspenseCounter = 0;
|
|
35
|
+
const serializeBoundaryChild = (child) => typeof child === "string" || Array.isArray(child) ? (0, import_base.renderChildren)([child]) : child == null || typeof child === "boolean" ? "" : (0, import_base.isUntrustedObject)(child) ? (0, import_base.renderUntrustedObject)(child) : child.toString();
|
|
35
36
|
const Suspense = async ({
|
|
36
37
|
children,
|
|
37
38
|
fallback
|
|
@@ -48,9 +49,7 @@ const Suspense = async ({
|
|
|
48
49
|
try {
|
|
49
50
|
stackNode[import_constants.DOM_STASH][0] = 0;
|
|
50
51
|
import_render.buildDataStack.push([[], stackNode]);
|
|
51
|
-
resArray = children.map(
|
|
52
|
-
(c) => c == null || typeof c === "boolean" ? "" : c.toString()
|
|
53
|
-
);
|
|
52
|
+
resArray = children.map(serializeBoundaryChild);
|
|
54
53
|
} catch (e) {
|
|
55
54
|
if (e instanceof Promise) {
|
|
56
55
|
const resume = (0, import_context.captureRenderContext)();
|
|
@@ -71,7 +70,7 @@ const Suspense = async ({
|
|
|
71
70
|
}
|
|
72
71
|
if (resArray.some((res) => res instanceof Promise)) {
|
|
73
72
|
const index = suspenseCounter++;
|
|
74
|
-
const fallbackStr = await fallback.toString();
|
|
73
|
+
const fallbackStr = await (typeof fallback === "string" || Array.isArray(fallback) ? (0, import_base.renderChildren)([fallback]) : (0, import_base.isUntrustedObject)(fallback) ? (0, import_base.renderUntrustedObject)(fallback) : fallback.toString());
|
|
75
74
|
return (0, import_html.raw)(`<template id="H:${index}"></template>${fallbackStr}<!--/$-->`, [
|
|
76
75
|
...fallbackStr.callbacks || [],
|
|
77
76
|
({ phase, buffer, context }) => {
|
|
@@ -84,7 +83,7 @@ const Suspense = async ({
|
|
|
84
83
|
if (buffer) {
|
|
85
84
|
buffer[0] = buffer[0].replace(
|
|
86
85
|
new RegExp(`<template id="H:${index}"></template>.*?<!--/\\$-->`),
|
|
87
|
-
content
|
|
86
|
+
() => content
|
|
88
87
|
);
|
|
89
88
|
}
|
|
90
89
|
let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script${nonce ? ` nonce="${nonce}"` : ""}>
|
|
@@ -44,7 +44,7 @@ const parseVaryDirectives = (vary) => {
|
|
|
44
44
|
};
|
|
45
45
|
const createCacheKey = (key, requestUrl, request, varyHeaders) => {
|
|
46
46
|
const url = new URL(cacheKeyPath, requestUrl);
|
|
47
|
-
url.searchParams.append(cacheKeyParameter, key
|
|
47
|
+
url.searchParams.append(cacheKeyParameter, key);
|
|
48
48
|
url.searchParams.append(cacheMethodKeyParameter, request.method);
|
|
49
49
|
if (request.method === "QUERY") {
|
|
50
50
|
url.searchParams.append(queryDigestKeyParameter, request.digest);
|
package/dist/cjs/utils/body.js
CHANGED
|
@@ -21,6 +21,8 @@ __export(body_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(body_exports);
|
|
23
23
|
var import_buffer = require("./buffer");
|
|
24
|
+
const MAX_NESTING_DEPTH = 32;
|
|
25
|
+
const MAX_NESTED_OBJECTS = 1e4;
|
|
24
26
|
const isRawRequest = (request) => "headers" in request;
|
|
25
27
|
const parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
26
28
|
const { all = false, dot = false } = options;
|
|
@@ -53,6 +55,7 @@ async function parseFormData(request, options) {
|
|
|
53
55
|
}
|
|
54
56
|
function convertFormDataToBodyData(formData, options) {
|
|
55
57
|
const form = /* @__PURE__ */ Object.create(null);
|
|
58
|
+
const nestingState = { count: 0 };
|
|
56
59
|
formData.forEach((value, key) => {
|
|
57
60
|
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
58
61
|
if (!shouldParseAllValues) {
|
|
@@ -65,7 +68,7 @@ function convertFormDataToBodyData(formData, options) {
|
|
|
65
68
|
Object.entries(form).forEach(([key, value]) => {
|
|
66
69
|
const shouldParseDotValues = key.includes(".");
|
|
67
70
|
if (shouldParseDotValues) {
|
|
68
|
-
handleParsingNestedValues(form, key, value);
|
|
71
|
+
handleParsingNestedValues(form, key, value, nestingState);
|
|
69
72
|
delete form[key];
|
|
70
73
|
}
|
|
71
74
|
});
|
|
@@ -88,23 +91,32 @@ const handleParsingAllValues = (form, key, value) => {
|
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
};
|
|
91
|
-
const handleParsingNestedValues = (form, key, value) => {
|
|
94
|
+
const handleParsingNestedValues = (form, key, value, state) => {
|
|
92
95
|
if (/(?:^|\.)__proto__\./.test(key)) {
|
|
93
96
|
return;
|
|
94
97
|
}
|
|
95
98
|
let nestedForm = form;
|
|
96
|
-
const keys = key.split(".");
|
|
99
|
+
const keys = key.split(".", MAX_NESTING_DEPTH + 2);
|
|
100
|
+
if (keys.length > MAX_NESTING_DEPTH + 1) {
|
|
101
|
+
throwNestingLimitExceeded();
|
|
102
|
+
}
|
|
97
103
|
keys.forEach((key2, index) => {
|
|
98
104
|
if (index === keys.length - 1) {
|
|
99
105
|
nestedForm[key2] = value;
|
|
100
106
|
} else {
|
|
101
107
|
if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
|
|
108
|
+
if (state.count++ >= MAX_NESTED_OBJECTS) {
|
|
109
|
+
throwNestingLimitExceeded();
|
|
110
|
+
}
|
|
102
111
|
nestedForm[key2] = /* @__PURE__ */ Object.create(null);
|
|
103
112
|
}
|
|
104
113
|
nestedForm = nestedForm[key2];
|
|
105
114
|
}
|
|
106
115
|
});
|
|
107
116
|
};
|
|
117
|
+
const throwNestingLimitExceeded = () => {
|
|
118
|
+
throw new Error("Nesting limit exceeded");
|
|
119
|
+
};
|
|
108
120
|
// Annotate the CommonJS export names for ESM import in node:
|
|
109
121
|
0 && (module.exports = {
|
|
110
122
|
parseBody
|
package/dist/cjs/utils/url.js
CHANGED
|
@@ -119,7 +119,11 @@ const getPath = (request) => {
|
|
|
119
119
|
};
|
|
120
120
|
const getQueryStrings = (url) => {
|
|
121
121
|
const queryIndex = url.indexOf("?", 8);
|
|
122
|
-
|
|
122
|
+
if (queryIndex === -1) {
|
|
123
|
+
return "";
|
|
124
|
+
}
|
|
125
|
+
const hashIndex = url.indexOf("#", 8);
|
|
126
|
+
return hashIndex === -1 ? url.slice(queryIndex) : queryIndex < hashIndex ? url.slice(queryIndex, hashIndex) : "";
|
|
123
127
|
};
|
|
124
128
|
const getPathNoStrict = (request) => {
|
|
125
129
|
const result = getPath(request);
|
|
@@ -166,6 +170,10 @@ const _decodeURI = (value) => {
|
|
|
166
170
|
return tryDecodeURIComponent(value);
|
|
167
171
|
};
|
|
168
172
|
const _getQueryParam = (url, key, multiple) => {
|
|
173
|
+
const hashIndex = url.indexOf("#", 8);
|
|
174
|
+
if (hashIndex !== -1) {
|
|
175
|
+
url = url.slice(0, hashIndex);
|
|
176
|
+
}
|
|
169
177
|
let encoded;
|
|
170
178
|
if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
|
|
171
179
|
let keyIndex2 = url.indexOf("?", 8);
|
package/dist/client/client.js
CHANGED
|
@@ -143,24 +143,24 @@ var hc = (baseUrl, options) => createProxy(function proxyCallback(opts) {
|
|
|
143
143
|
const path = parts.join("/");
|
|
144
144
|
const url = mergePath(baseUrl, path);
|
|
145
145
|
if (method === "url" || method === "path") {
|
|
146
|
-
let result = url;
|
|
146
|
+
let result = removeIndexString(url);
|
|
147
147
|
if (opts.args[0]) {
|
|
148
148
|
if (opts.args[0].param) {
|
|
149
|
-
result = replaceUrlParam(
|
|
149
|
+
result = replaceUrlParam(result, opts.args[0].param);
|
|
150
150
|
}
|
|
151
151
|
if (opts.args[0].query) {
|
|
152
152
|
result = appendQueryParams(result, buildSearchParamsOption(opts.args[0].query));
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
-
result = removeIndexString(result);
|
|
156
155
|
if (method === "url") {
|
|
157
156
|
return new URL(result);
|
|
158
157
|
}
|
|
159
158
|
return result.slice(baseUrl.replace(/\/+$/, "").length).replace(/^\/?/, "/");
|
|
160
159
|
}
|
|
161
160
|
if (method === "ws") {
|
|
161
|
+
const normalizedUrl = removeIndexString(url);
|
|
162
162
|
const webSocketUrl = replaceUrlProtocol(
|
|
163
|
-
opts.args[0]?.param ? replaceUrlParam(
|
|
163
|
+
opts.args[0]?.param ? replaceUrlParam(normalizedUrl, opts.args[0].param) : normalizedUrl,
|
|
164
164
|
"ws"
|
|
165
165
|
);
|
|
166
166
|
const targetUrl = new URL(webSocketUrl);
|
package/dist/helper/ssg/ssg.js
CHANGED
|
@@ -184,7 +184,7 @@ var saveContentToFile = async (data, fsModule, outDir, extensionMap) => {
|
|
|
184
184
|
const { routePath, content, mimeType } = awaitedData;
|
|
185
185
|
const filePath = generateFilePath(routePath, outDir, mimeType, extensionMap);
|
|
186
186
|
const dirPath = dirname(filePath);
|
|
187
|
-
if (!createdDirs.has(dirPath)) {
|
|
187
|
+
if (dirPath !== "" && !createdDirs.has(dirPath)) {
|
|
188
188
|
await fsModule.mkdir(dirPath, { recursive: true });
|
|
189
189
|
createdDirs.add(dirPath);
|
|
190
190
|
}
|
package/dist/helper/ssg/utils.js
CHANGED
|
@@ -8,8 +8,14 @@ var dirname = (path) => {
|
|
|
8
8
|
var normalizePath = (path) => {
|
|
9
9
|
return path.replace(/(\\)/g, "/").replace(/\/$/g, "");
|
|
10
10
|
};
|
|
11
|
-
var
|
|
12
|
-
|
|
11
|
+
var getUncRoot = (path) => {
|
|
12
|
+
const uncRoot = path.replace(/\\/g, "/").match(/^\/\/([^/]+)\/([^/]+)/);
|
|
13
|
+
if (uncRoot) {
|
|
14
|
+
return `${uncRoot[1].toLowerCase()}/${uncRoot[2].toLowerCase()}`;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var handleParent = (resultPaths) => {
|
|
18
|
+
if (resultPaths.length === 0 || resultPaths[resultPaths.length - 1] === "..") {
|
|
13
19
|
resultPaths.push("..");
|
|
14
20
|
} else {
|
|
15
21
|
resultPaths.pop();
|
|
@@ -22,22 +28,20 @@ var handleNonDot = (path, resultPaths) => {
|
|
|
22
28
|
}
|
|
23
29
|
};
|
|
24
30
|
var handleSegments = (paths, resultPaths) => {
|
|
25
|
-
let beforeParentFlag = false;
|
|
26
31
|
for (const path of paths) {
|
|
27
32
|
if (path === "..") {
|
|
28
|
-
handleParent(resultPaths
|
|
29
|
-
beforeParentFlag = true;
|
|
33
|
+
handleParent(resultPaths);
|
|
30
34
|
} else {
|
|
31
35
|
handleNonDot(path, resultPaths);
|
|
32
|
-
beforeParentFlag = false;
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
};
|
|
36
39
|
var joinPaths = (...paths) => {
|
|
40
|
+
const hasUncPrefix = getUncRoot(paths[0]) !== void 0;
|
|
37
41
|
paths = paths.map(normalizePath);
|
|
38
42
|
const resultPaths = [];
|
|
39
43
|
handleSegments(paths.join("/").split("/"), resultPaths);
|
|
40
|
-
return (paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
|
|
44
|
+
return (hasUncPrefix ? "//" : paths[0][0] === "/" ? "/" : "") + resultPaths.join("/");
|
|
41
45
|
};
|
|
42
46
|
var filterStaticGenerateRoutes = (hono) => {
|
|
43
47
|
return hono.routes.reduce((acc, { method, handler, path }) => {
|
|
@@ -51,10 +55,26 @@ var filterStaticGenerateRoutes = (hono) => {
|
|
|
51
55
|
var isDynamicRoute = (path) => {
|
|
52
56
|
return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*"));
|
|
53
57
|
};
|
|
58
|
+
var toSegments = (path) => path === "" ? [] : path.split("/");
|
|
59
|
+
var getPathRoot = (path) => {
|
|
60
|
+
const normalizedPath = path.replace(/\\/g, "/");
|
|
61
|
+
const uncRoot = getUncRoot(normalizedPath);
|
|
62
|
+
if (uncRoot) {
|
|
63
|
+
return `unc:${uncRoot}`;
|
|
64
|
+
}
|
|
65
|
+
const driveRoot = normalizedPath.match(/^([A-Za-z]):/);
|
|
66
|
+
if (driveRoot) {
|
|
67
|
+
const kind = normalizedPath[2] === "/" ? "drive-absolute" : "drive-relative";
|
|
68
|
+
return `${kind}:${driveRoot[1].toLowerCase()}`;
|
|
69
|
+
}
|
|
70
|
+
return normalizedPath.startsWith("/") ? "absolute" : "relative";
|
|
71
|
+
};
|
|
54
72
|
var ensureWithinOutDir = (outDir, filePath) => {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
73
|
+
const outDirSegments = toSegments(joinPaths(outDir));
|
|
74
|
+
const filePathSegments = toSegments(joinPaths(filePath));
|
|
75
|
+
const hasMismatchedPathRoot = getPathRoot(outDir) !== getPathRoot(filePath);
|
|
76
|
+
const climbsAboveOutDir = filePathSegments[outDirSegments.length] === "..";
|
|
77
|
+
if (hasMismatchedPathRoot || filePathSegments.length <= outDirSegments.length || !outDirSegments.every((segment, i) => segment === filePathSegments[i]) || climbsAboveOutDir) {
|
|
58
78
|
throw new Error(`Path traversal detected: "${filePath}" is outside the output directory`);
|
|
59
79
|
}
|
|
60
80
|
};
|
package/dist/hono-base.js
CHANGED
|
@@ -40,13 +40,14 @@ var Hono = class _Hono {
|
|
|
40
40
|
const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE];
|
|
41
41
|
allMethods.forEach((method) => {
|
|
42
42
|
this[method] = (args1, ...args) => {
|
|
43
|
+
const methodName = method.toUpperCase();
|
|
43
44
|
if (typeof args1 === "string") {
|
|
44
45
|
this.#path = args1;
|
|
45
46
|
} else {
|
|
46
|
-
this.#addRoute(
|
|
47
|
+
this.#addRoute(methodName, this.#path, args1);
|
|
47
48
|
}
|
|
48
49
|
args.forEach((handler) => {
|
|
49
|
-
this.#addRoute(
|
|
50
|
+
this.#addRoute(methodName, this.#path, handler);
|
|
50
51
|
});
|
|
51
52
|
return this;
|
|
52
53
|
};
|
|
@@ -55,9 +56,10 @@ var Hono = class _Hono {
|
|
|
55
56
|
for (const p of [path].flat()) {
|
|
56
57
|
this.#path = p;
|
|
57
58
|
for (const m of [method].flat()) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const methodName = m.toUpperCase();
|
|
60
|
+
for (const handler of handlers) {
|
|
61
|
+
this.#addRoute(methodName, this.#path, handler);
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
return this;
|
|
@@ -258,7 +260,6 @@ var Hono = class _Hono {
|
|
|
258
260
|
return this;
|
|
259
261
|
}
|
|
260
262
|
#addRoute(method, path, handler, baseRoutePath) {
|
|
261
|
-
method = method.toUpperCase();
|
|
262
263
|
path = mergePath(this._basePath, path);
|
|
263
264
|
const r = {
|
|
264
265
|
basePath: baseRoutePath !== void 0 ? mergePath(this._basePath, baseRoutePath) : this._basePath,
|
package/dist/jsx/base.js
CHANGED
|
@@ -70,7 +70,7 @@ var booleanAttributes = [
|
|
|
70
70
|
"selected"
|
|
71
71
|
];
|
|
72
72
|
var resolveFunctionComponentResult = (result, suspendedContext) => result.then((resolved) => {
|
|
73
|
-
if (!Array.isArray(resolved) && !(resolved instanceof JSXNode)) {
|
|
73
|
+
if (typeof resolved !== "string" && !Array.isArray(resolved) && !(resolved instanceof JSXNode)) {
|
|
74
74
|
return resolved;
|
|
75
75
|
}
|
|
76
76
|
const children = Array.isArray(resolved) ? resolved : [resolved];
|
|
@@ -108,6 +108,17 @@ var childrenToStringToBuffer = (children, buffer) => {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
|
+
var renderChildren = (children) => runWithRenderContext(() => {
|
|
112
|
+
const buffer = [""];
|
|
113
|
+
childrenToStringToBuffer(children, buffer);
|
|
114
|
+
return buffer.length === 1 ? raw(buffer[0], buffer.callbacks) : stringBufferToString(buffer, buffer.callbacks);
|
|
115
|
+
});
|
|
116
|
+
var isUntrustedObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof JSXNode) && !(value instanceof Promise) && !value.isEscaped && typeof value.toString === "function";
|
|
117
|
+
var renderUntrustedObject = (value) => {
|
|
118
|
+
const stringified = value.toString();
|
|
119
|
+
const escape = (result) => renderChildren([String(result)]);
|
|
120
|
+
return stringified instanceof Promise ? stringified.then(escape) : escape(stringified);
|
|
121
|
+
};
|
|
111
122
|
var JSXNode = class {
|
|
112
123
|
tag;
|
|
113
124
|
props;
|
|
@@ -337,10 +348,13 @@ export {
|
|
|
337
348
|
booleanAttributes,
|
|
338
349
|
cloneElement,
|
|
339
350
|
getNameSpaceContext,
|
|
351
|
+
isUntrustedObject,
|
|
340
352
|
isValidElement,
|
|
341
353
|
jsx,
|
|
342
354
|
jsxFn,
|
|
343
355
|
memo,
|
|
344
356
|
reactAPICompatVersion,
|
|
357
|
+
renderChildren,
|
|
358
|
+
renderUntrustedObject,
|
|
345
359
|
shallowEqual
|
|
346
360
|
};
|
package/dist/jsx/components.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/jsx/components.ts
|
|
2
2
|
import { raw } from "../helper/html/index.js";
|
|
3
3
|
import { HtmlEscapedCallbackPhase, resolveCallback } from "../utils/html.js";
|
|
4
|
-
import { jsx, Fragment } from "./base.js";
|
|
4
|
+
import { jsx, Fragment, isUntrustedObject, renderChildren, renderUntrustedObject } from "./base.js";
|
|
5
5
|
import { DOM_RENDERER } from "./constants.js";
|
|
6
6
|
import { captureRenderContext, useContext } from "./context.js";
|
|
7
7
|
import { ErrorBoundary as ErrorBoundaryDomRenderer } from "./dom/components.js";
|
|
@@ -9,7 +9,7 @@ import { StreamingContext } from "./streaming.js";
|
|
|
9
9
|
var errorBoundaryCounter = 0;
|
|
10
10
|
var childrenToString = async (children) => {
|
|
11
11
|
try {
|
|
12
|
-
return children.flat().map(
|
|
12
|
+
return children.flat().map(resolveChildEarly);
|
|
13
13
|
} catch (e) {
|
|
14
14
|
if (e instanceof Promise) {
|
|
15
15
|
const resume = captureRenderContext();
|
|
@@ -20,18 +20,16 @@ var childrenToString = async (children) => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
var resolveChildEarly = (
|
|
24
|
-
if (
|
|
23
|
+
var resolveChildEarly = (child) => {
|
|
24
|
+
if (child == null || typeof child === "boolean") {
|
|
25
25
|
return "";
|
|
26
|
-
} else if (typeof
|
|
27
|
-
return
|
|
26
|
+
} else if (typeof child === "string" || Array.isArray(child)) {
|
|
27
|
+
return renderChildren([child]);
|
|
28
|
+
} else if (isUntrustedObject(child)) {
|
|
29
|
+
return renderUntrustedObject(child);
|
|
28
30
|
} else {
|
|
29
|
-
const str =
|
|
30
|
-
|
|
31
|
-
return raw(str);
|
|
32
|
-
} else {
|
|
33
|
-
return str;
|
|
34
|
-
}
|
|
31
|
+
const str = child.toString();
|
|
32
|
+
return str instanceof Promise ? str : raw(str);
|
|
35
33
|
}
|
|
36
34
|
};
|
|
37
35
|
var ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
|
|
@@ -47,26 +45,27 @@ var ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
|
|
|
47
45
|
let fallbackStrPromise;
|
|
48
46
|
const resolveFallbackStr = () => fallbackStrPromise ||= (async () => {
|
|
49
47
|
const awaitedFallback = await fallback;
|
|
50
|
-
if (
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
}
|
|
48
|
+
if (awaitedFallback === null || awaitedFallback === void 0) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (typeof awaitedFallback === "string" || Array.isArray(awaitedFallback)) {
|
|
52
|
+
return getResume()(() => renderChildren([awaitedFallback]));
|
|
53
|
+
}
|
|
54
|
+
if (isUntrustedObject(awaitedFallback)) {
|
|
55
|
+
return getResume()(() => renderUntrustedObject(awaitedFallback));
|
|
60
56
|
}
|
|
57
|
+
const fallbackResult = await getResume()(() => awaitedFallback.toString());
|
|
58
|
+
return raw(
|
|
59
|
+
fallbackResult,
|
|
60
|
+
fallbackResult.callbacks || awaitedFallback.callbacks
|
|
61
|
+
);
|
|
61
62
|
})();
|
|
62
63
|
const renderFallback = async (error) => {
|
|
63
64
|
const fallbackStr = await resolveFallbackStr();
|
|
64
65
|
return getResume()(async () => {
|
|
65
66
|
onError?.(error);
|
|
66
67
|
const fallbackRes = fallbackStr !== void 0 ? fallbackStr : fallbackRender && jsx(Fragment, {}, fallbackRender(error)) || "";
|
|
67
|
-
const fallbackResString = await Fragment({
|
|
68
|
-
children: fallbackRes
|
|
69
|
-
}).toString();
|
|
68
|
+
const fallbackResString = await Fragment({ children: fallbackRes }).toString();
|
|
70
69
|
return raw(
|
|
71
70
|
fallbackResString,
|
|
72
71
|
fallbackResString.callbacks || fallbackRes.callbacks
|
|
@@ -99,7 +98,7 @@ var ErrorBoundary = async ({ children, fallback, fallbackRender, onError }) => {
|
|
|
99
98
|
const fallbackResString = await renderFallback(error2);
|
|
100
99
|
const fallbackCallbacks = fallbackResString.callbacks;
|
|
101
100
|
if (buffer) {
|
|
102
|
-
buffer[0] = buffer[0].replace(replaceRe, fallbackResString);
|
|
101
|
+
buffer[0] = buffer[0].replace(replaceRe, () => fallbackResString);
|
|
103
102
|
return fallbackCallbacks?.length ? raw("", fallbackCallbacks) : "";
|
|
104
103
|
}
|
|
105
104
|
return raw(
|
|
@@ -138,7 +137,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
|
|
|
138
137
|
</script>`;
|
|
139
138
|
if (htmlArray.every((html2) => !html2.callbacks?.length)) {
|
|
140
139
|
if (buffer) {
|
|
141
|
-
buffer[0] = buffer[0].replace(replaceRe, content);
|
|
140
|
+
buffer[0] = buffer[0].replace(replaceRe, () => content);
|
|
142
141
|
}
|
|
143
142
|
return html;
|
|
144
143
|
}
|
package/dist/jsx/context.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/jsx/context.ts
|
|
2
2
|
import { raw } from "../helper/html/index.js";
|
|
3
|
-
import { JSXFragmentNode } from "./base.js";
|
|
3
|
+
import { isUntrustedObject, JSXFragmentNode, renderChildren, renderUntrustedObject } from "./base.js";
|
|
4
4
|
import { DOM_RENDERER } from "./constants.js";
|
|
5
5
|
import { createContextProviderFunction } from "./dom/context.js";
|
|
6
6
|
var globalContexts = [];
|
|
@@ -130,18 +130,18 @@ var createContext = (defaultValue) => {
|
|
|
130
130
|
const context = ((props) => {
|
|
131
131
|
const contextValues = getContextValuesIn(getCurrentStore(), context);
|
|
132
132
|
contextValues.push(props.value);
|
|
133
|
-
let
|
|
133
|
+
let rendered;
|
|
134
134
|
try {
|
|
135
|
-
|
|
135
|
+
rendered = typeof props.children === "string" ? renderChildren([props.children]) : isUntrustedObject(props.children) ? renderUntrustedObject(props.children) : props.children ? (Array.isArray(props.children) ? new JSXFragmentNode("", {}, props.children) : props.children).toString() : raw("");
|
|
136
136
|
} catch (e) {
|
|
137
137
|
contextValues.pop();
|
|
138
138
|
throw e;
|
|
139
139
|
}
|
|
140
|
-
if (
|
|
141
|
-
return
|
|
140
|
+
if (rendered instanceof Promise) {
|
|
141
|
+
return rendered.finally(() => contextValues.pop()).then((resString) => raw(resString, resString.callbacks));
|
|
142
142
|
} else {
|
|
143
143
|
contextValues.pop();
|
|
144
|
-
return raw(
|
|
144
|
+
return raw(rendered);
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
context.values = values;
|
package/dist/jsx/dom/server.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// src/jsx/dom/server.ts
|
|
2
|
+
import { renderChildren } from "../base.js";
|
|
2
3
|
import { renderToReadableStream as renderToReadableStreamHono } from "../streaming.js";
|
|
3
4
|
import version from "./index.js";
|
|
5
|
+
var prepareRoot = (element) => typeof element === "string" || Array.isArray(element) ? renderChildren([element]) : element;
|
|
4
6
|
var renderToString = (element, options = {}) => {
|
|
5
7
|
if (Object.keys(options).length > 0) {
|
|
6
8
|
console.warn("options are not supported yet");
|
|
7
9
|
}
|
|
8
|
-
|
|
10
|
+
element = prepareRoot(element);
|
|
11
|
+
const res = element instanceof Promise ? element : element?.toString() ?? "";
|
|
9
12
|
if (typeof res !== "string") {
|
|
10
13
|
throw new Error("Async component is not supported in renderToString");
|
|
11
14
|
}
|
|
@@ -15,6 +18,7 @@ var renderToReadableStream = async (element, options = {}) => {
|
|
|
15
18
|
if (Object.keys(options).some((key) => key !== "onError")) {
|
|
16
19
|
console.warn("options are not supported yet, except onError");
|
|
17
20
|
}
|
|
21
|
+
element = prepareRoot(element);
|
|
18
22
|
if (!element || typeof element !== "object") {
|
|
19
23
|
element = element?.toString() ?? "";
|
|
20
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/jsx/intrinsic-element/components.ts
|
|
2
2
|
import { raw } from "../../helper/html/index.js";
|
|
3
|
-
import { JSXNode, getNameSpaceContext } from "../base.js";
|
|
3
|
+
import { JSXNode, getNameSpaceContext, renderChildren } from "../base.js";
|
|
4
4
|
import { toArray } from "../children.js";
|
|
5
5
|
import { PERMALINK } from "../constants.js";
|
|
6
6
|
import { useContext } from "../context.js";
|
|
@@ -62,10 +62,10 @@ var insertIntoHead = (tagName, tag, props, precedence) => ({ buffer, context })
|
|
|
62
62
|
insertTags.forEach((tag2) => {
|
|
63
63
|
buffer[0] = buffer[0].replaceAll(tag2, "");
|
|
64
64
|
});
|
|
65
|
-
buffer[0] = buffer[0].replace(/(?=<\/head>)/, insertTags.join(""));
|
|
65
|
+
buffer[0] = buffer[0].replace(/(?=<\/head>)/, () => insertTags.join(""));
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
-
var returnWithoutSpecialBehavior = (tag, children, props) =>
|
|
68
|
+
var returnWithoutSpecialBehavior = (tag, children, props) => renderChildren([new JSXNode(tag, props, toArray(children ?? []))]);
|
|
69
69
|
var documentMetadataTag = (tag, children, props, sort) => {
|
|
70
70
|
if ("itemProp" in props) {
|
|
71
71
|
return returnWithoutSpecialBehavior(tag, children, props);
|
package/dist/jsx/streaming.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/jsx/streaming.ts
|
|
2
2
|
import { raw } from "../helper/html/index.js";
|
|
3
3
|
import { HtmlEscapedCallbackPhase, resolveCallback } from "../utils/html.js";
|
|
4
|
-
import { JSXNode } from "./base.js";
|
|
4
|
+
import { isUntrustedObject, JSXNode, renderChildren, renderUntrustedObject } from "./base.js";
|
|
5
5
|
import { childrenToString } from "./components.js";
|
|
6
6
|
import { DOM_RENDERER, DOM_STASH } from "./constants.js";
|
|
7
7
|
import { captureRenderContext, createContext, useContext } from "./context.js";
|
|
@@ -9,6 +9,7 @@ import { Suspense as SuspenseDomRenderer } from "./dom/components.js";
|
|
|
9
9
|
import { buildDataStack } from "./dom/render.js";
|
|
10
10
|
var StreamingContext = createContext(null);
|
|
11
11
|
var suspenseCounter = 0;
|
|
12
|
+
var serializeBoundaryChild = (child) => typeof child === "string" || Array.isArray(child) ? renderChildren([child]) : child == null || typeof child === "boolean" ? "" : isUntrustedObject(child) ? renderUntrustedObject(child) : child.toString();
|
|
12
13
|
var Suspense = async ({
|
|
13
14
|
children,
|
|
14
15
|
fallback
|
|
@@ -25,9 +26,7 @@ var Suspense = async ({
|
|
|
25
26
|
try {
|
|
26
27
|
stackNode[DOM_STASH][0] = 0;
|
|
27
28
|
buildDataStack.push([[], stackNode]);
|
|
28
|
-
resArray = children.map(
|
|
29
|
-
(c) => c == null || typeof c === "boolean" ? "" : c.toString()
|
|
30
|
-
);
|
|
29
|
+
resArray = children.map(serializeBoundaryChild);
|
|
31
30
|
} catch (e) {
|
|
32
31
|
if (e instanceof Promise) {
|
|
33
32
|
const resume = captureRenderContext();
|
|
@@ -48,7 +47,7 @@ var Suspense = async ({
|
|
|
48
47
|
}
|
|
49
48
|
if (resArray.some((res) => res instanceof Promise)) {
|
|
50
49
|
const index = suspenseCounter++;
|
|
51
|
-
const fallbackStr = await fallback.toString();
|
|
50
|
+
const fallbackStr = await (typeof fallback === "string" || Array.isArray(fallback) ? renderChildren([fallback]) : isUntrustedObject(fallback) ? renderUntrustedObject(fallback) : fallback.toString());
|
|
52
51
|
return raw(`<template id="H:${index}"></template>${fallbackStr}<!--/$-->`, [
|
|
53
52
|
...fallbackStr.callbacks || [],
|
|
54
53
|
({ phase, buffer, context }) => {
|
|
@@ -61,7 +60,7 @@ var Suspense = async ({
|
|
|
61
60
|
if (buffer) {
|
|
62
61
|
buffer[0] = buffer[0].replace(
|
|
63
62
|
new RegExp(`<template id="H:${index}"></template>.*?<!--/\\$-->`),
|
|
64
|
-
content
|
|
63
|
+
() => content
|
|
65
64
|
);
|
|
66
65
|
}
|
|
67
66
|
let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script${nonce ? ` nonce="${nonce}"` : ""}>
|
|
@@ -23,7 +23,7 @@ var parseVaryDirectives = (vary) => {
|
|
|
23
23
|
};
|
|
24
24
|
var createCacheKey = (key, requestUrl, request, varyHeaders) => {
|
|
25
25
|
const url = new URL(cacheKeyPath, requestUrl);
|
|
26
|
-
url.searchParams.append(cacheKeyParameter, key
|
|
26
|
+
url.searchParams.append(cacheKeyParameter, key);
|
|
27
27
|
url.searchParams.append(cacheMethodKeyParameter, request.method);
|
|
28
28
|
if (request.method === "QUERY") {
|
|
29
29
|
url.searchParams.append(queryDigestKeyParameter, request.digest);
|
package/dist/types/context.d.ts
CHANGED
|
@@ -347,7 +347,7 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
|
|
|
347
347
|
* ```
|
|
348
348
|
*/
|
|
349
349
|
set: Set<IsAny<E> extends true ? {
|
|
350
|
-
Variables: ContextVariableMap & Record<
|
|
350
|
+
Variables: ContextVariableMap & Record<PropertyKey, any>;
|
|
351
351
|
} : E>;
|
|
352
352
|
/**
|
|
353
353
|
* `.get()` can use the value specified by the key.
|
|
@@ -363,7 +363,7 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
|
|
|
363
363
|
* ```
|
|
364
364
|
*/
|
|
365
365
|
get: Get<IsAny<E> extends true ? {
|
|
366
|
-
Variables: ContextVariableMap & Record<
|
|
366
|
+
Variables: ContextVariableMap & Record<PropertyKey, any>;
|
|
367
367
|
} : E>;
|
|
368
368
|
/**
|
|
369
369
|
* `.var` can access the value of a variable.
|
package/dist/types/jsx/base.d.ts
CHANGED
|
@@ -26,6 +26,9 @@ export declare namespace JSX {
|
|
|
26
26
|
export declare const getNameSpaceContext: () => Context<string> | undefined;
|
|
27
27
|
export declare const booleanAttributes: string[];
|
|
28
28
|
export type Child = string | Promise<string> | number | JSXNode | null | undefined | boolean | Child[];
|
|
29
|
+
export declare const renderChildren: (children: Child[]) => HtmlEscapedString | Promise<HtmlEscapedString>;
|
|
30
|
+
export declare const isUntrustedObject: (value: unknown) => boolean;
|
|
31
|
+
export declare const renderUntrustedObject: (value: unknown) => HtmlEscapedString | Promise<HtmlEscapedString>;
|
|
29
32
|
export declare class JSXNode implements HtmlEscaped {
|
|
30
33
|
tag: string | Function;
|
|
31
34
|
props: Props;
|
|
@@ -19,6 +19,10 @@ export declare const tryDecode: (str: string, decoder: Decoder) => string;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare const tryDecodeURI: (str: string) => string;
|
|
21
21
|
export declare const getPath: (request: Request) => string;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
* Use the `URL` API instead.
|
|
25
|
+
*/
|
|
22
26
|
export declare const getQueryStrings: (url: string) => string;
|
|
23
27
|
export declare const getPathNoStrict: (request: Request) => string;
|
|
24
28
|
/**
|
package/dist/utils/body.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/utils/body.ts
|
|
2
2
|
import { bufferToFormData } from "./buffer.js";
|
|
3
|
+
var MAX_NESTING_DEPTH = 32;
|
|
4
|
+
var MAX_NESTED_OBJECTS = 1e4;
|
|
3
5
|
var isRawRequest = (request) => "headers" in request;
|
|
4
6
|
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
5
7
|
const { all = false, dot = false } = options;
|
|
@@ -32,6 +34,7 @@ async function parseFormData(request, options) {
|
|
|
32
34
|
}
|
|
33
35
|
function convertFormDataToBodyData(formData, options) {
|
|
34
36
|
const form = /* @__PURE__ */ Object.create(null);
|
|
37
|
+
const nestingState = { count: 0 };
|
|
35
38
|
formData.forEach((value, key) => {
|
|
36
39
|
const shouldParseAllValues = options.all || key.endsWith("[]");
|
|
37
40
|
if (!shouldParseAllValues) {
|
|
@@ -44,7 +47,7 @@ function convertFormDataToBodyData(formData, options) {
|
|
|
44
47
|
Object.entries(form).forEach(([key, value]) => {
|
|
45
48
|
const shouldParseDotValues = key.includes(".");
|
|
46
49
|
if (shouldParseDotValues) {
|
|
47
|
-
handleParsingNestedValues(form, key, value);
|
|
50
|
+
handleParsingNestedValues(form, key, value, nestingState);
|
|
48
51
|
delete form[key];
|
|
49
52
|
}
|
|
50
53
|
});
|
|
@@ -67,23 +70,32 @@ var handleParsingAllValues = (form, key, value) => {
|
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
};
|
|
70
|
-
var handleParsingNestedValues = (form, key, value) => {
|
|
73
|
+
var handleParsingNestedValues = (form, key, value, state) => {
|
|
71
74
|
if (/(?:^|\.)__proto__\./.test(key)) {
|
|
72
75
|
return;
|
|
73
76
|
}
|
|
74
77
|
let nestedForm = form;
|
|
75
|
-
const keys = key.split(".");
|
|
78
|
+
const keys = key.split(".", MAX_NESTING_DEPTH + 2);
|
|
79
|
+
if (keys.length > MAX_NESTING_DEPTH + 1) {
|
|
80
|
+
throwNestingLimitExceeded();
|
|
81
|
+
}
|
|
76
82
|
keys.forEach((key2, index) => {
|
|
77
83
|
if (index === keys.length - 1) {
|
|
78
84
|
nestedForm[key2] = value;
|
|
79
85
|
} else {
|
|
80
86
|
if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
|
|
87
|
+
if (state.count++ >= MAX_NESTED_OBJECTS) {
|
|
88
|
+
throwNestingLimitExceeded();
|
|
89
|
+
}
|
|
81
90
|
nestedForm[key2] = /* @__PURE__ */ Object.create(null);
|
|
82
91
|
}
|
|
83
92
|
nestedForm = nestedForm[key2];
|
|
84
93
|
}
|
|
85
94
|
});
|
|
86
95
|
};
|
|
96
|
+
var throwNestingLimitExceeded = () => {
|
|
97
|
+
throw new Error("Nesting limit exceeded");
|
|
98
|
+
};
|
|
87
99
|
export {
|
|
88
100
|
parseBody
|
|
89
101
|
};
|
package/dist/utils/url.js
CHANGED
|
@@ -85,7 +85,11 @@ var getPath = (request) => {
|
|
|
85
85
|
};
|
|
86
86
|
var getQueryStrings = (url) => {
|
|
87
87
|
const queryIndex = url.indexOf("?", 8);
|
|
88
|
-
|
|
88
|
+
if (queryIndex === -1) {
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
const hashIndex = url.indexOf("#", 8);
|
|
92
|
+
return hashIndex === -1 ? url.slice(queryIndex) : queryIndex < hashIndex ? url.slice(queryIndex, hashIndex) : "";
|
|
89
93
|
};
|
|
90
94
|
var getPathNoStrict = (request) => {
|
|
91
95
|
const result = getPath(request);
|
|
@@ -132,6 +136,10 @@ var _decodeURI = (value) => {
|
|
|
132
136
|
return tryDecodeURIComponent(value);
|
|
133
137
|
};
|
|
134
138
|
var _getQueryParam = (url, key, multiple) => {
|
|
139
|
+
const hashIndex = url.indexOf("#", 8);
|
|
140
|
+
if (hashIndex !== -1) {
|
|
141
|
+
url = url.slice(0, hashIndex);
|
|
142
|
+
}
|
|
135
143
|
let encoded;
|
|
136
144
|
if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
|
|
137
145
|
let keyIndex2 = url.indexOf("?", 8);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/hono",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.7-depup.0",
|
|
4
4
|
"description": "Web framework built on Web Standards (with updated dependencies)",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -686,7 +686,7 @@
|
|
|
686
686
|
"@typescript/native-preview": "7.0.0-dev.20260210.1",
|
|
687
687
|
"@vitest/coverage-v8": "^4.1.7",
|
|
688
688
|
"bun-types": "^1.2.20",
|
|
689
|
-
"editorconfig-checker": "6.
|
|
689
|
+
"editorconfig-checker": "6.2.0",
|
|
690
690
|
"esbuild": "^0.27.1",
|
|
691
691
|
"eslint": "^9.39.3",
|
|
692
692
|
"jsdom": "22.1.0",
|
|
@@ -711,8 +711,8 @@
|
|
|
711
711
|
"changes": {},
|
|
712
712
|
"depsUpdated": 0,
|
|
713
713
|
"originalPackage": "hono",
|
|
714
|
-
"originalVersion": "4.13.
|
|
715
|
-
"processedAt": "2026-
|
|
714
|
+
"originalVersion": "4.13.7",
|
|
715
|
+
"processedAt": "2026-09-05T00:31:41.567Z",
|
|
716
716
|
"smokeTest": "passed"
|
|
717
717
|
}
|
|
718
718
|
}
|