@shopify/hydrogen 2026.4.7 → 2026.4.8

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.
@@ -0,0 +1,80 @@
1
+ // src/vite/dev-tooling-guard.ts
2
+ var TUNNEL_HOST_SUFFIXES = [".trycloudflare.com", ".tryhydrogen.dev"];
3
+ var DEV_TOOL_ROUTES = [
4
+ "/graphiql",
5
+ "/subrequest-profiler",
6
+ "/debug-network-server"
7
+ ];
8
+ var LOOPBACK_V4_PREFIX = "127.";
9
+ var LOOPBACK_V6 = "::1";
10
+ var MAPPED_LOOPBACK_PREFIX = "::ffff:127.";
11
+ function isLoopback(addr) {
12
+ if (!addr) return false;
13
+ return addr.startsWith(LOOPBACK_V4_PREFIX) || addr === LOOPBACK_V6 || addr.startsWith(MAPPED_LOOPBACK_PREFIX);
14
+ }
15
+ function hostFromHeader(raw) {
16
+ if (!raw) return "";
17
+ if (raw.startsWith("[")) {
18
+ const bracketEnd = raw.indexOf("]");
19
+ if (bracketEnd !== -1) return raw.slice(1, bracketEnd);
20
+ }
21
+ const colonIdx = raw.lastIndexOf(":");
22
+ return colonIdx > 0 ? raw.slice(0, colonIdx) : raw;
23
+ }
24
+ function isTunnelHost(hostname) {
25
+ const lower = hostname.toLowerCase().replace(/\.$/, "");
26
+ return TUNNEL_HOST_SUFFIXES.some((suffix) => lower.endsWith(suffix));
27
+ }
28
+ function isDevToolRoute(pathname) {
29
+ const path = pathname.toLowerCase();
30
+ for (const route of DEV_TOOL_ROUTES) {
31
+ if (!path.startsWith(route)) continue;
32
+ const border = path[route.length];
33
+ if (border === void 0 || border === "/" || border === ".") return true;
34
+ }
35
+ return false;
36
+ }
37
+ function isRemoteDevToolingRequest(params) {
38
+ if (!isDevToolRoute(params.pathname)) return false;
39
+ if (isTunnelHost(hostFromHeader(params.host))) return true;
40
+ return !isLoopback(params.remoteAddress);
41
+ }
42
+ function createDevToolingGuard() {
43
+ return (req, res, next) => {
44
+ const raw = req.url ?? "";
45
+ if (raw !== "" && !raw.startsWith("/") && !raw.startsWith("?")) {
46
+ res.writeHead(400, { "Content-Type": "text/plain" });
47
+ res.end("Bad Request");
48
+ return;
49
+ }
50
+ const rawPath = raw.split("?")[0] ?? "";
51
+ let resolvedPath;
52
+ try {
53
+ const canonical = new URL(raw || "/", "http://n").pathname;
54
+ try {
55
+ resolvedPath = decodeURIComponent(canonical);
56
+ } catch {
57
+ resolvedPath = canonical;
58
+ }
59
+ } catch {
60
+ res.writeHead(400, { "Content-Type": "text/plain" });
61
+ res.end("Bad Request");
62
+ return;
63
+ }
64
+ const check = {
65
+ host: req.headers.host,
66
+ remoteAddress: req.socket?.remoteAddress
67
+ };
68
+ if (isRemoteDevToolingRequest({ pathname: rawPath, ...check }) || isRemoteDevToolingRequest({ pathname: resolvedPath, ...check })) {
69
+ res.writeHead(404, { "Content-Type": "text/plain" });
70
+ res.end("Hydrogen dev tooling is only available from localhost.");
71
+ return;
72
+ }
73
+ next();
74
+ };
75
+ }
76
+
77
+ export {
78
+ isRemoteDevToolingRequest,
79
+ createDevToolingGuard
80
+ };
@@ -0,0 +1,10 @@
1
+ import { Connect } from 'vite';
2
+
3
+ declare function isRemoteDevToolingRequest(params: {
4
+ pathname: string;
5
+ host: string | undefined;
6
+ remoteAddress: string | undefined;
7
+ }): boolean;
8
+ declare function createDevToolingGuard(): Connect.NextHandleFunction;
9
+
10
+ export { createDevToolingGuard, isRemoteDevToolingRequest };
@@ -0,0 +1,8 @@
1
+ import {
2
+ createDevToolingGuard,
3
+ isRemoteDevToolingRequest
4
+ } from "./chunk-IHK6YKEW.js";
5
+ export {
6
+ createDevToolingGuard,
7
+ isRemoteDevToolingRequest
8
+ };
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  getCompatDate
3
3
  } from "./chunk-FAQ7TVHC.js";
4
+ import {
5
+ createDevToolingGuard
6
+ } from "./chunk-IHK6YKEW.js";
4
7
  import {
5
8
  setupHydrogenMiddleware
6
9
  } from "./chunk-QXBQVDMY.js";
@@ -149,6 +152,7 @@ function hydrogen(pluginOptions = {}) {
149
152
  configureServer: {
150
153
  order: "pre",
151
154
  handler: (viteDevServer) => {
155
+ viteDevServer.middlewares.use(createDevToolingGuard());
152
156
  return () => {
153
157
  setupHydrogenMiddleware(
154
158
  viteDevServer,
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "@shopify:registry": "https://registry.npmjs.org"
6
6
  },
7
7
  "type": "module",
8
- "version": "2026.4.7",
8
+ "version": "2026.4.8",
9
9
  "license": "MIT",
10
10
  "main": "dist/index.cjs",
11
11
  "module": "dist/production/index.js",
@@ -80,7 +80,7 @@
80
80
  "use-resize-observer": "^9.1.0",
81
81
  "worktop": "^0.7.3",
82
82
  "@shopify/graphql-client": "1.4.1",
83
- "@shopify/hydrogen-react": "2026.4.4"
83
+ "@shopify/hydrogen-react": "2026.4.5"
84
84
  },
85
85
  "devDependencies": {
86
86
  "react-router": "7.16.0",