@utoo/pack 1.3.0 → 1.3.2-alpha.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.
@@ -18,6 +18,7 @@ const https_1 = __importDefault(require("https"));
18
18
  const path_1 = __importDefault(require("path"));
19
19
  const webpackCompat_1 = require("../config/webpackCompat");
20
20
  const hmr_1 = require("../core/hmr");
21
+ const proxy_hono_1 = require("../core/proxy-hono");
21
22
  const common_1 = require("../utils/common");
22
23
  const findRoot_1 = require("../utils/findRoot");
23
24
  const mkcert_1 = require("../utils/mkcert");
@@ -138,7 +139,7 @@ function serve(options, projectPath, rootPath, serverOptions) {
138
139
  }
139
140
  const HMR_PATH = "/turbopack-hmr";
140
141
  async function runDev(options, projectPath, rootPath, serverOptions) {
141
- var _a, _b, _d, _e;
142
+ var _a, _b, _d, _e, _f, _g;
142
143
  (0, common_1.blockStdout)();
143
144
  process.title = "utoopack-dev-server";
144
145
  if (process.env.XCODE_PROFILE) {
@@ -190,6 +191,10 @@ async function runDev(options, projectPath, rootPath, serverOptions) {
190
191
  console.error("HMR WebSocket error", err);
191
192
  },
192
193
  })));
194
+ const proxyRules = (_g = (_f = bundleOptions.config) === null || _f === void 0 ? void 0 : _f.devServer) === null || _g === void 0 ? void 0 : _g.proxy;
195
+ if (proxyRules && proxyRules.length > 0) {
196
+ app.use("*", (0, proxy_hono_1.createHttpProxyMiddleware)(proxyRules));
197
+ }
193
198
  // GET handles HEAD automatically in Hono; serveStatic serves both
194
199
  app.get("/*", (0, serve_static_1.serveStatic)({
195
200
  root: distRoot,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * HTTP proxy middleware for Hono dev server.
3
+ * Matches ProxyRule by path, applies pathRewrite, and forwards via Hono proxy().
4
+ * No generic WS proxying in this module.
5
+ */
6
+ import type { DevServerProxy, PathRewrite, ProxyRule } from "@utoo/pack-shared";
7
+ import type { Context, Next } from "hono";
8
+ /** Path prefix or ^-prefixed regex match (regex tests full path). */
9
+ export declare function doesContextMatchUrl(context: string, pathOrUrl: string): boolean;
10
+ export declare function ruleMatchesUrl(rule: ProxyRule, pathOrUrl: string): boolean;
11
+ /**
12
+ * Apply pathRewrite (http-proxy-middleware style).
13
+ * Object: first matching regex → replace, then stop. Function: (path) => new path.
14
+ */
15
+ export declare function applyPathRewrite(path: string, pathRewrite?: PathRewrite): string;
16
+ export interface PreparedProxyRequest {
17
+ url: URL;
18
+ headers: Headers;
19
+ }
20
+ /**
21
+ * Build target URL and headers for the proxy request from current context and rule.
22
+ */
23
+ export declare function prepareProxyRequest(c: Context, rule: ProxyRule): PreparedProxyRequest;
24
+ /**
25
+ * Hono middleware: on match, proxy to rule.target with pathRewrite and changeOrigin;
26
+ * on error return 502; otherwise next().
27
+ * Caller (e.g. dev.ts) must pass a non-empty array; empty array means no rule matches.
28
+ */
29
+ export declare function createHttpProxyMiddleware(rules: DevServerProxy): (c: Context, next: Next) => Promise<void | Response>;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /**
3
+ * HTTP proxy middleware for Hono dev server.
4
+ * Matches ProxyRule by path, applies pathRewrite, and forwards via Hono proxy().
5
+ * No generic WS proxying in this module.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.doesContextMatchUrl = doesContextMatchUrl;
9
+ exports.ruleMatchesUrl = ruleMatchesUrl;
10
+ exports.applyPathRewrite = applyPathRewrite;
11
+ exports.prepareProxyRequest = prepareProxyRequest;
12
+ exports.createHttpProxyMiddleware = createHttpProxyMiddleware;
13
+ const proxy_1 = require("hono/proxy");
14
+ /** Path prefix or ^-prefixed regex match (regex tests full path). */
15
+ function doesContextMatchUrl(context, pathOrUrl) {
16
+ if (context[0] === "^") {
17
+ try {
18
+ return new RegExp(context).test(pathOrUrl);
19
+ }
20
+ catch (_a) {
21
+ return false;
22
+ }
23
+ }
24
+ return pathOrUrl === context || pathOrUrl.startsWith(context + "/");
25
+ }
26
+ function ruleMatchesUrl(rule, pathOrUrl) {
27
+ const contexts = Array.isArray(rule.context) ? rule.context : [rule.context];
28
+ return contexts.some((ctx) => doesContextMatchUrl(ctx, pathOrUrl));
29
+ }
30
+ /**
31
+ * Apply pathRewrite (http-proxy-middleware style).
32
+ * Object: first matching regex → replace, then stop. Function: (path) => new path.
33
+ */
34
+ function applyPathRewrite(path, pathRewrite) {
35
+ if (!pathRewrite)
36
+ return path;
37
+ if (typeof pathRewrite === "function") {
38
+ return pathRewrite(path);
39
+ }
40
+ for (const [pattern, value] of Object.entries(pathRewrite)) {
41
+ try {
42
+ const regex = new RegExp(pattern);
43
+ if (regex.test(path)) {
44
+ return path.replace(regex, value);
45
+ }
46
+ }
47
+ catch (_a) {
48
+ // invalid regex, skip
49
+ }
50
+ }
51
+ return path;
52
+ }
53
+ /**
54
+ * Build target URL and headers for the proxy request from current context and rule.
55
+ */
56
+ function prepareProxyRequest(c, rule) {
57
+ const origUrl = new URL(c.req.url);
58
+ const targetUrl = new URL(rule.target);
59
+ const origPath = c.req.path;
60
+ const rewrittenPath = applyPathRewrite(origPath, rule.pathRewrite);
61
+ targetUrl.pathname = rewrittenPath;
62
+ targetUrl.search = origUrl.search;
63
+ const headers = new Headers(c.req.header());
64
+ if (rule.changeOrigin !== false) {
65
+ headers.set("host", targetUrl.host);
66
+ }
67
+ return { url: targetUrl, headers };
68
+ }
69
+ /**
70
+ * Hono middleware: on match, proxy to rule.target with pathRewrite and changeOrigin;
71
+ * on error return 502; otherwise next().
72
+ * Caller (e.g. dev.ts) must pass a non-empty array; empty array means no rule matches.
73
+ */
74
+ function createHttpProxyMiddleware(rules) {
75
+ return async (c, next) => {
76
+ const rule = rules.find((r) => ruleMatchesUrl(r, c.req.path));
77
+ if (!rule) {
78
+ return next();
79
+ }
80
+ try {
81
+ const prepared = prepareProxyRequest(c, rule);
82
+ const init = {
83
+ method: c.req.method,
84
+ headers: prepared.headers,
85
+ };
86
+ if (c.req.method !== "GET" && c.req.method !== "HEAD") {
87
+ init.body = c.req.raw.body;
88
+ }
89
+ return (0, proxy_1.proxy)(prepared.url.toString(), init);
90
+ }
91
+ catch (err) {
92
+ console.error("[dev proxy] error", c.req.method, c.req.url, err);
93
+ return c.text("Bad Gateway", 502);
94
+ }
95
+ };
96
+ }
@@ -12,6 +12,7 @@ import https from "https";
12
12
  import path from "path";
13
13
  import { resolveBundleOptions, } from "../config/webpackCompat.js";
14
14
  import { createHotReloader } from "../core/hmr.js";
15
+ import { createHttpProxyMiddleware } from "../core/proxy-hono.js";
15
16
  import { blockStdout, getPackPath } from "../utils/common.js";
16
17
  import { findRootDir } from "../utils/findRoot.js";
17
18
  import { createSelfSignedCertificate } from "../utils/mkcert.js";
@@ -132,7 +133,7 @@ export function serve(options, projectPath, rootPath, serverOptions) {
132
133
  }
133
134
  const HMR_PATH = "/turbopack-hmr";
134
135
  async function runDev(options, projectPath, rootPath, serverOptions) {
135
- var _a, _b, _d, _e;
136
+ var _a, _b, _d, _e, _f, _g;
136
137
  blockStdout();
137
138
  process.title = "utoopack-dev-server";
138
139
  if (process.env.XCODE_PROFILE) {
@@ -184,6 +185,10 @@ async function runDev(options, projectPath, rootPath, serverOptions) {
184
185
  console.error("HMR WebSocket error", err);
185
186
  },
186
187
  })));
188
+ const proxyRules = (_g = (_f = bundleOptions.config) === null || _f === void 0 ? void 0 : _f.devServer) === null || _g === void 0 ? void 0 : _g.proxy;
189
+ if (proxyRules && proxyRules.length > 0) {
190
+ app.use("*", createHttpProxyMiddleware(proxyRules));
191
+ }
187
192
  // GET handles HEAD automatically in Hono; serveStatic serves both
188
193
  app.get("/*", serveStatic({
189
194
  root: distRoot,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * HTTP proxy middleware for Hono dev server.
3
+ * Matches ProxyRule by path, applies pathRewrite, and forwards via Hono proxy().
4
+ * No generic WS proxying in this module.
5
+ */
6
+ import type { DevServerProxy, PathRewrite, ProxyRule } from "@utoo/pack-shared";
7
+ import type { Context, Next } from "hono";
8
+ /** Path prefix or ^-prefixed regex match (regex tests full path). */
9
+ export declare function doesContextMatchUrl(context: string, pathOrUrl: string): boolean;
10
+ export declare function ruleMatchesUrl(rule: ProxyRule, pathOrUrl: string): boolean;
11
+ /**
12
+ * Apply pathRewrite (http-proxy-middleware style).
13
+ * Object: first matching regex → replace, then stop. Function: (path) => new path.
14
+ */
15
+ export declare function applyPathRewrite(path: string, pathRewrite?: PathRewrite): string;
16
+ export interface PreparedProxyRequest {
17
+ url: URL;
18
+ headers: Headers;
19
+ }
20
+ /**
21
+ * Build target URL and headers for the proxy request from current context and rule.
22
+ */
23
+ export declare function prepareProxyRequest(c: Context, rule: ProxyRule): PreparedProxyRequest;
24
+ /**
25
+ * Hono middleware: on match, proxy to rule.target with pathRewrite and changeOrigin;
26
+ * on error return 502; otherwise next().
27
+ * Caller (e.g. dev.ts) must pass a non-empty array; empty array means no rule matches.
28
+ */
29
+ export declare function createHttpProxyMiddleware(rules: DevServerProxy): (c: Context, next: Next) => Promise<void | Response>;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * HTTP proxy middleware for Hono dev server.
3
+ * Matches ProxyRule by path, applies pathRewrite, and forwards via Hono proxy().
4
+ * No generic WS proxying in this module.
5
+ */
6
+ import { proxy } from "hono/proxy";
7
+ /** Path prefix or ^-prefixed regex match (regex tests full path). */
8
+ export function doesContextMatchUrl(context, pathOrUrl) {
9
+ if (context[0] === "^") {
10
+ try {
11
+ return new RegExp(context).test(pathOrUrl);
12
+ }
13
+ catch (_a) {
14
+ return false;
15
+ }
16
+ }
17
+ return pathOrUrl === context || pathOrUrl.startsWith(context + "/");
18
+ }
19
+ export function ruleMatchesUrl(rule, pathOrUrl) {
20
+ const contexts = Array.isArray(rule.context) ? rule.context : [rule.context];
21
+ return contexts.some((ctx) => doesContextMatchUrl(ctx, pathOrUrl));
22
+ }
23
+ /**
24
+ * Apply pathRewrite (http-proxy-middleware style).
25
+ * Object: first matching regex → replace, then stop. Function: (path) => new path.
26
+ */
27
+ export function applyPathRewrite(path, pathRewrite) {
28
+ if (!pathRewrite)
29
+ return path;
30
+ if (typeof pathRewrite === "function") {
31
+ return pathRewrite(path);
32
+ }
33
+ for (const [pattern, value] of Object.entries(pathRewrite)) {
34
+ try {
35
+ const regex = new RegExp(pattern);
36
+ if (regex.test(path)) {
37
+ return path.replace(regex, value);
38
+ }
39
+ }
40
+ catch (_a) {
41
+ // invalid regex, skip
42
+ }
43
+ }
44
+ return path;
45
+ }
46
+ /**
47
+ * Build target URL and headers for the proxy request from current context and rule.
48
+ */
49
+ export function prepareProxyRequest(c, rule) {
50
+ const origUrl = new URL(c.req.url);
51
+ const targetUrl = new URL(rule.target);
52
+ const origPath = c.req.path;
53
+ const rewrittenPath = applyPathRewrite(origPath, rule.pathRewrite);
54
+ targetUrl.pathname = rewrittenPath;
55
+ targetUrl.search = origUrl.search;
56
+ const headers = new Headers(c.req.header());
57
+ if (rule.changeOrigin !== false) {
58
+ headers.set("host", targetUrl.host);
59
+ }
60
+ return { url: targetUrl, headers };
61
+ }
62
+ /**
63
+ * Hono middleware: on match, proxy to rule.target with pathRewrite and changeOrigin;
64
+ * on error return 502; otherwise next().
65
+ * Caller (e.g. dev.ts) must pass a non-empty array; empty array means no rule matches.
66
+ */
67
+ export function createHttpProxyMiddleware(rules) {
68
+ return async (c, next) => {
69
+ const rule = rules.find((r) => ruleMatchesUrl(r, c.req.path));
70
+ if (!rule) {
71
+ return next();
72
+ }
73
+ try {
74
+ const prepared = prepareProxyRequest(c, rule);
75
+ const init = {
76
+ method: c.req.method,
77
+ headers: prepared.headers,
78
+ };
79
+ if (c.req.method !== "GET" && c.req.method !== "HEAD") {
80
+ init.body = c.req.raw.body;
81
+ }
82
+ return proxy(prepared.url.toString(), init);
83
+ }
84
+ catch (err) {
85
+ console.error("[dev proxy] error", c.req.method, c.req.url, err);
86
+ return c.text("Bad Gateway", 502);
87
+ }
88
+ };
89
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utoo/pack",
3
- "version": "1.3.0",
3
+ "version": "1.3.2-alpha.0",
4
4
  "main": "cjs/index.js",
5
5
  "module": "esm/index.js",
6
6
  "types": "esm/index.d.ts",
@@ -41,7 +41,7 @@
41
41
  "@hono/node-server": "^1.19.11",
42
42
  "@hono/node-ws": "^1.3.0",
43
43
  "@swc/helpers": "0.5.15",
44
- "@utoo/pack-shared": "1.3.0",
44
+ "@utoo/pack-shared": "1.3.2-alpha.0",
45
45
  "@utoo/style-loader": "^1.0.0",
46
46
  "domparser-rs": "^0.0.7",
47
47
  "find-up": "4.1.0",
@@ -90,12 +90,12 @@
90
90
  },
91
91
  "repository": "git@github.com:utooland/utoo.git",
92
92
  "optionalDependencies": {
93
- "@utoo/pack-darwin-arm64": "1.3.0",
94
- "@utoo/pack-darwin-x64": "1.3.0",
95
- "@utoo/pack-linux-arm64-gnu": "1.3.0",
96
- "@utoo/pack-linux-arm64-musl": "1.3.0",
97
- "@utoo/pack-linux-x64-gnu": "1.3.0",
98
- "@utoo/pack-linux-x64-musl": "1.3.0",
99
- "@utoo/pack-win32-x64-msvc": "1.3.0"
93
+ "@utoo/pack-darwin-arm64": "1.3.2-alpha.0",
94
+ "@utoo/pack-darwin-x64": "1.3.2-alpha.0",
95
+ "@utoo/pack-linux-arm64-gnu": "1.3.2-alpha.0",
96
+ "@utoo/pack-linux-arm64-musl": "1.3.2-alpha.0",
97
+ "@utoo/pack-linux-x64-gnu": "1.3.2-alpha.0",
98
+ "@utoo/pack-linux-x64-musl": "1.3.2-alpha.0",
99
+ "@utoo/pack-win32-x64-msvc": "1.3.2-alpha.0"
100
100
  }
101
101
  }