@maintainer-pro/ai-bridge 0.1.15 → 0.1.18

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,32 @@
1
+ /**
2
+ * Leftover quick-tunnel cleanup from before Maintainer Pro share URLs.
3
+ * Keep this file small; do not add new tunnel machinery here.
4
+ */
5
+
6
+ const leftoverVendor = ["cloud", "flare"].join("");
7
+ const leftoverName = new RegExp(leftoverVendor, "i");
8
+
9
+ export const LEGACY_TUNNEL_FILE = `.${leftoverVendor}-tunnel-url`;
10
+
11
+ export function isDiscardedTunnelUrl(value) {
12
+ try {
13
+ return new URL(String(value || "").trim()).hostname.endsWith(
14
+ `.try${leftoverVendor}.com`
15
+ );
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ export function leftoverStateKeys(obj) {
22
+ if (!obj || typeof obj !== "object") return [];
23
+ return Object.keys(obj).filter((key) => leftoverName.test(key));
24
+ }
25
+
26
+ /** Queued jobs from before share-proxy used these codes. */
27
+ export function canonicalActionCode(code) {
28
+ const value = String(code || "");
29
+ if (!leftoverName.test(value)) return value;
30
+ if (value.startsWith("start_")) return "start_share_app";
31
+ return "configure_share";
32
+ }
@@ -79,7 +79,8 @@ export function prepareShareHttpRequest(
79
79
  headers,
80
80
  publicBase,
81
81
  acceptEncodingHint,
82
- path
82
+ path,
83
+ portUrls
83
84
  ) {
84
85
  const out = { ...headers };
85
86
  const acceptEncoding = String(
@@ -116,6 +117,13 @@ export function prepareShareHttpRequest(
116
117
  /* ignore */
117
118
  }
118
119
  }
120
+ if (portUrls && typeof portUrls === "object") {
121
+ for (const key of Object.keys(out)) {
122
+ const lower = key.toLowerCase();
123
+ if (lower === "host" || lower === "content-length") continue;
124
+ out[key] = rewriteMappedLocalUrls(out[key], portUrls);
125
+ }
126
+ }
119
127
  return { headers: out, acceptEncoding, ifNoneMatch };
120
128
  }
121
129
 
@@ -123,14 +131,23 @@ export function shouldRewriteBody(headers) {
123
131
  const enc = headerGet(headers, "content-encoding").toLowerCase();
124
132
  if (enc && enc !== "identity") return false;
125
133
  const ct = headerGet(headers, "content-type").toLowerCase();
126
- return /html|javascript|ecmascript|css|json|svg|xml|text\/plain|text\/x-component|text\/x-ref|\brsc\b/.test(
134
+ if (/event-stream|octet-stream|image\/|audio\/|video\/|font\/|wasm/.test(ct)) {
135
+ return false;
136
+ }
137
+ return /html|javascript|ecmascript|css|json|svg|xml|text\/|urlencoded|x-component|x-ref|\brsc\b/.test(
127
138
  ct
128
139
  );
129
140
  }
130
141
 
131
142
  /** Redirects have no Content-Type, but Location still has to stay under the share prefix. */
132
143
  export function shouldProcessShareResponse(headers) {
133
- return Boolean(headerGet(headers, "location")) || shouldRewriteBody(headers);
144
+ if (headerGet(headers, "location")) return true;
145
+ if (shouldRewriteBody(headers)) return true;
146
+ const ct = headerGet(headers, "content-type").toLowerCase();
147
+ if (ct) return false;
148
+ const len = Number(headerGet(headers, "content-length") || 0);
149
+ if (len > 2 * 1024 * 1024) return false;
150
+ return true;
134
151
  }
135
152
 
136
153
  function isImmutableAssetPath(path) {
@@ -155,7 +172,8 @@ function isNoStorePath(path) {
155
172
  /\/@vite(?:\/|$)/.test(p) ||
156
173
  /\/@react-refresh/.test(p) ||
157
174
  /\/@fs\//.test(p) ||
158
- /\/@id\//.test(p)
175
+ /\/@id\//.test(p) ||
176
+ /\/__mp\//.test(p)
159
177
  );
160
178
  }
161
179
 
@@ -240,30 +258,199 @@ function notModifiedResult(headers, etag) {
240
258
  return { status: 304, headers: out, body: Buffer.alloc(0) };
241
259
  }
242
260
 
243
- function rewriteLocation(value, publicBase, port) {
244
- if (!publicBase) return value;
245
- const base = String(publicBase).replace(/\/$/, "");
261
+ function isLoopbackHost(host) {
262
+ const name = String(host || "").toLowerCase().replace(/^\[|\]$/g, "");
263
+ return (
264
+ name === "127.0.0.1" ||
265
+ name === "localhost" ||
266
+ name === "::1" ||
267
+ name === "0.0.0.0"
268
+ );
269
+ }
270
+
271
+ function mappedUrlForPort(portUrls, port) {
272
+ if (!portUrls || !port) return "";
273
+ const dest = portUrls[port] || portUrls[String(port)];
274
+ return dest ? String(dest).replace(/\/$/, "") : "";
275
+ }
276
+
277
+ function isProbablyUtf8Text(buf) {
278
+ if (!Buffer.isBuffer(buf) || !buf.length || buf.length > 8 * 1024 * 1024) {
279
+ return false;
280
+ }
281
+ const sample = buf.subarray(0, Math.min(buf.length, 4096));
282
+ if (sample.includes(0)) return false;
283
+ return true;
284
+ }
285
+
286
+ /**
287
+ * Replace app-list origins (`localhost:8080`, LAN IPs, hostnames) with the
288
+ * share URL for that port. Self-contained so the browser shim/SW can embed it.
289
+ *
290
+ * @param {string} text
291
+ * @param {Record<string, string> | null | undefined} portUrls
292
+ */
293
+ export function rewriteMappedLocalUrls(text, portUrls) {
294
+ if (!text || !portUrls) return text;
295
+ const ports = Object.keys(portUrls)
296
+ .map((key) => Number(key))
297
+ .filter((port) => Number.isInteger(port) && port > 0 && port <= 65535)
298
+ .sort((a, b) => b - a);
299
+ if (!ports.length) return text;
300
+ const localHost =
301
+ "(?:localhost|127\\.0\\.0\\.1|\\[::1\\]|::1|0\\.0\\.0\\.0|" +
302
+ "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
303
+ "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
304
+ "172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|" +
305
+ "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
306
+ "[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.(?:local|lan|internal|home))?)";
307
+ const anyHost = "(?:[^\\s'\"\\\\/<>@:]+|\\[[0-9a-fA-F:]+\\])";
308
+ let out = String(text);
309
+ for (let i = 0; i < ports.length; i++) {
310
+ const port = ports[i];
311
+ const dest = String(portUrls[port] || portUrls[String(port)] || "").replace(
312
+ /\/$/,
313
+ ""
314
+ );
315
+ if (!dest) continue;
316
+ const destWs = dest.replace(/^http/i, "ws");
317
+ const destEsc = dest.replace(/\//g, "\\/");
318
+ const destWsEsc = destWs.replace(/\//g, "\\/");
319
+ const tail = "(?!\\d)";
320
+ const swap = function (matched, replacement) {
321
+ if (!matched) return matched;
322
+ if (dest.indexOf(matched) === 0 || destWs.indexOf(matched) === 0) {
323
+ return matched;
324
+ }
325
+ return replacement;
326
+ };
327
+ out = out.replace(new RegExp("https?://" + localHost + ":" + port + tail, "gi"), function (m) {
328
+ return swap(m, dest);
329
+ });
330
+ out = out.replace(new RegExp("wss?://" + localHost + ":" + port + tail, "gi"), function (m) {
331
+ return swap(m, destWs);
332
+ });
333
+ out = out.replace(new RegExp("https?:\\\\/\\\\/" + localHost + ":" + port + tail, "gi"), function (m) {
334
+ return swap(m, destEsc);
335
+ });
336
+ out = out.replace(new RegExp("wss?:\\\\/\\\\/" + localHost + ":" + port + tail, "gi"), function (m) {
337
+ return swap(m, destWsEsc);
338
+ });
339
+ out = out.replace(new RegExp("//" + localHost + ":" + port + tail, "gi"), function (m) {
340
+ return swap(m, dest.replace(/^https?:/i, ""));
341
+ });
342
+ out = out.replace(new RegExp("http://" + anyHost + ":" + port + tail, "gi"), function (m) {
343
+ return swap(m, dest);
344
+ });
345
+ out = out.replace(new RegExp("ws://" + anyHost + ":" + port + tail, "gi"), function (m) {
346
+ return swap(m, destWs);
347
+ });
348
+ out = out.replace(
349
+ new RegExp("(?<![\\w./])" + localHost + ":" + port + tail, "gi"),
350
+ function (m) {
351
+ return swap(m, dest);
352
+ }
353
+ );
354
+ }
355
+ return out;
356
+ }
357
+
358
+ /**
359
+ * @param {Buffer | string | null | undefined} body
360
+ * @param {Record<string, string>} headers
361
+ * @param {Record<string, string> | null | undefined} portUrls
362
+ */
363
+ export function rewriteShareRequestBody(body, headers, portUrls) {
364
+ if (!body || !portUrls || !Object.keys(portUrls).length) return body;
365
+ const buf = Buffer.isBuffer(body) ? body : Buffer.from(body);
366
+ if (!buf.length) return buf;
367
+ if (!shouldRewriteBody(headers) && !isProbablyUtf8Text(buf)) return buf;
368
+ const text = buf.toString("utf8");
369
+ const next = rewriteMappedLocalUrls(text, portUrls);
370
+ if (next === text) return buf;
371
+ return Buffer.from(next, "utf8");
372
+ }
373
+
374
+ export function shareTokenRoot(publicBase) {
246
375
  const prefix = proxyPathPrefix(publicBase);
376
+ if (!prefix) return "";
377
+ const parts = prefix.split("/").filter(Boolean);
378
+ if (parts[0] === "p" && parts[1]) return `/${parts[0]}/${parts[1]}/`;
379
+ return prefix.endsWith("/") ? prefix : `${prefix}/`;
380
+ }
381
+
382
+ export function shareShimScript(pathPrefix, portUrls) {
383
+ return `(${shareProxyShim.toString()})(${JSON.stringify(pathPrefix || "")},${JSON.stringify(portUrls || {})},${rewriteMappedLocalUrls.toString()});`;
384
+ }
385
+
386
+ export function shareServiceWorkerScript(portUrls, tokenRoot) {
387
+ return `(${shareServiceWorkerMain.toString()})(${JSON.stringify(portUrls || {})},${JSON.stringify(tokenRoot || "/")},${rewriteMappedLocalUrls.toString()});`;
388
+ }
389
+
390
+ function rewriteHeaderUrls(headers, publicBase, port, portUrls) {
391
+ if (headers.location) {
392
+ headers.location = rewriteLocation(
393
+ headers.location,
394
+ publicBase,
395
+ port,
396
+ portUrls
397
+ );
398
+ }
399
+ if (headers.link) {
400
+ headers.link = rewriteLinkHeader(headers.link, publicBase);
401
+ }
402
+ if (headers["access-control-allow-origin"]) {
403
+ headers["access-control-allow-origin"] = rewriteAllowOrigin(
404
+ headers["access-control-allow-origin"],
405
+ publicBase
406
+ );
407
+ }
408
+ if (!(portUrls && Object.keys(portUrls).length)) return;
409
+ for (const key of Object.keys(headers)) {
410
+ const lower = key.toLowerCase();
411
+ if (lower === "set-cookie" || lower === "content-length" || lower === "content-encoding") {
412
+ continue;
413
+ }
414
+ headers[key] = rewriteMappedLocalUrls(headers[key], portUrls);
415
+ }
416
+ }
417
+
418
+ function rewriteLocation(value, publicBase, port, portUrls) {
419
+ if (!publicBase && !(portUrls && Object.keys(portUrls).length)) return value;
247
420
  try {
248
421
  const u = new URL(value, `http://127.0.0.1:${Number(port) || 0}`);
249
- const host = String(u.hostname || "").toLowerCase();
250
- const local =
251
- host === "127.0.0.1" ||
252
- host === "localhost" ||
253
- host === "::1" ||
254
- host === "0.0.0.0";
255
- if (!local) return value;
422
+ if (!isLoopbackHost(u.hostname)) {
423
+ return rewriteMappedLocalUrls(String(value), portUrls);
424
+ }
425
+ const locPort = Number(u.port) || Number(port) || 0;
426
+ const mapped =
427
+ mappedUrlForPort(portUrls, locPort) ||
428
+ String(publicBase || "").replace(/\/$/, "");
429
+ if (!mapped) return value;
430
+ const prefix = proxyPathPrefix(mapped);
256
431
  let path = u.pathname || "/";
257
432
  if (prefix && (path === prefix || path.startsWith(`${prefix}/`))) {
258
433
  path = path.slice(prefix.length) || "/";
259
434
  }
260
- return `${base}${path}${u.search}${u.hash}`;
435
+ if (path === "/") return `${mapped}${u.search}${u.hash}`;
436
+ return `${mapped}${path}${u.search}${u.hash}`;
261
437
  } catch {
262
438
  /* keep */
263
439
  }
264
440
  return value;
265
441
  }
266
442
 
443
+ function rewriteAllowOrigin(value, publicBase) {
444
+ if (!value || value === "*" || !publicBase) return value;
445
+ try {
446
+ const u = new URL(value);
447
+ if (!isLoopbackHost(u.hostname)) return value;
448
+ return new URL(publicBase).origin;
449
+ } catch {
450
+ return value;
451
+ }
452
+ }
453
+
267
454
  function rewriteLinkHeader(value, publicBase) {
268
455
  const prefix = proxyPathPrefix(publicBase);
269
456
  if (!prefix || !value) return value;
@@ -686,11 +873,22 @@ function injectMaintainerProEmbed(html, aiPublicBase) {
686
873
  }
687
874
 
688
875
  /**
689
- * In-page rewrite: navigation stays under the share prefix; fetch/XHR/WebSocket
690
- * only touch same-origin Vite/Next assets. Other hosts are left unchanged.
876
+ * Intercept every browser request and map listed app ports onto share URLs.
691
877
  */
692
- function shareProxyShim(p) {
693
- if (!p) return;
878
+ function shareProxyShim(p, portMap, rewriteMappedLocalUrls) {
879
+ if (!p || window.__MP_SHARE_SHIM__) return;
880
+ window.__MP_SHARE_SHIM__ = 1;
881
+ window.__MP_PORT_MAP__ = portMap || {};
882
+ function rewriteText(text) {
883
+ if (typeof text !== "string" || !text || typeof rewriteMappedLocalUrls !== "function") {
884
+ return text;
885
+ }
886
+ try {
887
+ return rewriteMappedLocalUrls(text, portMap);
888
+ } catch (e) {
889
+ return text;
890
+ }
891
+ }
694
892
  function collapse(path) {
695
893
  var d = p + p;
696
894
  while (path.indexOf(d) === 0) path = p + path.slice(d.length);
@@ -718,8 +916,34 @@ function shareProxyShim(p) {
718
916
  }
719
917
  return path;
720
918
  }
919
+ function mapLocal(v) {
920
+ if (typeof v !== "string" || !v) return v;
921
+ if (
922
+ v.indexOf("blob:") === 0 ||
923
+ v.indexOf("data:") === 0 ||
924
+ v.indexOf("javascript:") === 0
925
+ ) {
926
+ return v;
927
+ }
928
+ var raw = v;
929
+ if (
930
+ v.indexOf("://") < 0 &&
931
+ /^(localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0):\d+/i.test(v)
932
+ ) {
933
+ raw = "http://" + v;
934
+ }
935
+ var next = rewriteText(raw);
936
+ if (next !== raw) return next;
937
+ try {
938
+ var u = new URL(v, location.href);
939
+ var resolved = rewriteText(u.href);
940
+ if (resolved !== u.href) return resolved;
941
+ } catch (e) {}
942
+ return v;
943
+ }
721
944
  function addNav(v) {
722
945
  if (typeof v !== "string" || !v) return v;
946
+ v = mapLocal(v);
723
947
  if (v.charAt(0) === "/" && v.charAt(1) !== "/") return prefixPath(v);
724
948
  try {
725
949
  var nav = new URL(v, location.href);
@@ -731,6 +955,8 @@ function shareProxyShim(p) {
731
955
  }
732
956
  function addNet(v) {
733
957
  if (typeof v !== "string" || !v) return v;
958
+ var mapped = mapLocal(v);
959
+ if (mapped !== v) return mapped;
734
960
  try {
735
961
  if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(v) || v.indexOf("//") === 0) {
736
962
  var net = new URL(v, location.href);
@@ -776,11 +1002,22 @@ function shareProxyShim(p) {
776
1002
  patchQS(Element.prototype, "querySelectorAll");
777
1003
  var sa = Element.prototype.setAttribute;
778
1004
  Element.prototype.setAttribute = function (n, v) {
779
- if ((n === "src" || n === "href") && typeof v === "string") v = addNav(v);
1005
+ var name = String(n || "").toLowerCase();
1006
+ if (
1007
+ (name === "src" ||
1008
+ name === "href" ||
1009
+ name === "action" ||
1010
+ name === "poster" ||
1011
+ name === "data-src") &&
1012
+ typeof v === "string"
1013
+ ) {
1014
+ v = addNav(v);
1015
+ }
780
1016
  return sa.call(this, n, v);
781
1017
  };
782
1018
  function patchUrlProp(ctor, prop) {
783
1019
  try {
1020
+ if (!ctor || !ctor.prototype) return;
784
1021
  var d = Object.getOwnPropertyDescriptor(ctor.prototype, prop);
785
1022
  if (!d || !d.set) return;
786
1023
  Object.defineProperty(ctor.prototype, prop, {
@@ -795,6 +1032,13 @@ function shareProxyShim(p) {
795
1032
  }
796
1033
  patchUrlProp(HTMLScriptElement, "src");
797
1034
  patchUrlProp(HTMLLinkElement, "href");
1035
+ patchUrlProp(HTMLAnchorElement, "href");
1036
+ patchUrlProp(HTMLImageElement, "src");
1037
+ patchUrlProp(HTMLIFrameElement, "src");
1038
+ patchUrlProp(HTMLFormElement, "action");
1039
+ patchUrlProp(HTMLSourceElement, "src");
1040
+ patchUrlProp(HTMLVideoElement, "src");
1041
+ patchUrlProp(HTMLAudioElement, "src");
798
1042
  var f = window.fetch;
799
1043
  window.fetch = function (input, init) {
800
1044
  if (typeof input === "string") input = addNet(input);
@@ -803,6 +1047,9 @@ function shareProxyShim(p) {
803
1047
  } else if (typeof URL !== "undefined" && input instanceof URL) {
804
1048
  input = new URL(addNet(input.href));
805
1049
  }
1050
+ if (init && typeof init.body === "string") {
1051
+ init = Object.assign({}, init, { body: rewriteText(init.body) });
1052
+ }
806
1053
  return f.call(this, input, init);
807
1054
  };
808
1055
  var xo = XMLHttpRequest.prototype.open;
@@ -810,6 +1057,11 @@ function shareProxyShim(p) {
810
1057
  if (typeof u === "string") arguments[1] = addNet(u);
811
1058
  return xo.apply(this, arguments);
812
1059
  };
1060
+ var xs = XMLHttpRequest.prototype.send;
1061
+ XMLHttpRequest.prototype.send = function (body) {
1062
+ if (typeof body === "string") arguments[0] = rewriteText(body);
1063
+ return xs.apply(this, arguments);
1064
+ };
813
1065
  var ps = history.pushState.bind(history);
814
1066
  history.pushState = function (s, t, u) {
815
1067
  if (typeof u === "string") u = addNav(u);
@@ -823,6 +1075,7 @@ function shareProxyShim(p) {
823
1075
  var WS = window.WebSocket;
824
1076
  function WrappedWS(url, protocols) {
825
1077
  if (typeof url === "string") url = addNet(url);
1078
+ else if (typeof URL !== "undefined" && url instanceof URL) url = addNet(url.href);
826
1079
  return protocols !== undefined ? new WS(url, protocols) : new WS(url);
827
1080
  }
828
1081
  WrappedWS.prototype = WS.prototype;
@@ -831,6 +1084,30 @@ function shareProxyShim(p) {
831
1084
  WrappedWS.CLOSING = WS.CLOSING;
832
1085
  WrappedWS.CLOSED = WS.CLOSED;
833
1086
  window.WebSocket = WrappedWS;
1087
+ if (window.EventSource) {
1088
+ var ES = window.EventSource;
1089
+ function WrappedES(url, config) {
1090
+ if (typeof url === "string") url = addNet(url);
1091
+ return config !== undefined ? new ES(url, config) : new ES(url);
1092
+ }
1093
+ WrappedES.prototype = ES.prototype;
1094
+ WrappedES.CONNECTING = ES.CONNECTING;
1095
+ WrappedES.OPEN = ES.OPEN;
1096
+ WrappedES.CLOSED = ES.CLOSED;
1097
+ window.EventSource = WrappedES;
1098
+ }
1099
+ if (navigator.sendBeacon) {
1100
+ var sb = navigator.sendBeacon.bind(navigator);
1101
+ navigator.sendBeacon = function (url, data) {
1102
+ if (typeof data === "string") data = rewriteText(data);
1103
+ return sb(addNet(String(url)), data);
1104
+ };
1105
+ }
1106
+ var wo = window.open;
1107
+ window.open = function (url) {
1108
+ if (typeof url === "string") arguments[0] = addNav(url);
1109
+ return wo.apply(this, arguments);
1110
+ };
834
1111
  try {
835
1112
  var la = location.assign.bind(location);
836
1113
  location.assign = function (u) {
@@ -856,19 +1133,102 @@ function shareProxyShim(p) {
856
1133
  });
857
1134
  }
858
1135
  } catch (e) {}
1136
+ try {
1137
+ var tokenRoot = p.replace(/\/[^/]+$/, "/");
1138
+ if (navigator.serviceWorker && tokenRoot.indexOf("/p/") === 0) {
1139
+ navigator.serviceWorker.register(p + "/__mp/sw.js", { scope: tokenRoot });
1140
+ }
1141
+ } catch (e) {}
1142
+ }
1143
+
1144
+ function shareServiceWorkerMain(portMap, tokenRoot, rewriteMappedLocalUrls) {
1145
+ self.addEventListener("install", function (event) {
1146
+ event.waitUntil(self.skipWaiting());
1147
+ });
1148
+ self.addEventListener("activate", function (event) {
1149
+ event.waitUntil(self.clients.claim());
1150
+ });
1151
+ function rewriteText(text) {
1152
+ if (typeof text !== "string" || !text) return text;
1153
+ try {
1154
+ return rewriteMappedLocalUrls(text, portMap);
1155
+ } catch (e) {
1156
+ return text;
1157
+ }
1158
+ }
1159
+ function mapUrl(v) {
1160
+ if (typeof v !== "string" || !v) return v;
1161
+ if (v.indexOf("/__mp/") !== -1) return v;
1162
+ return rewriteText(v);
1163
+ }
1164
+ self.addEventListener("fetch", function (event) {
1165
+ var req = event.request;
1166
+ if (req.url.indexOf("/__mp/") !== -1) return;
1167
+ event.respondWith(
1168
+ (async function () {
1169
+ var url = mapUrl(req.url);
1170
+ var method = req.method;
1171
+ var headers = new Headers(req.headers);
1172
+ var body;
1173
+ if (method !== "GET" && method !== "HEAD") {
1174
+ try {
1175
+ var ct = headers.get("content-type") || "";
1176
+ if (/json|text|xml|urlencoded|javascript/.test(ct) || !ct) {
1177
+ var text = await req.clone().text();
1178
+ var next = rewriteText(text);
1179
+ if (next !== text) body = next;
1180
+ }
1181
+ } catch (e) {}
1182
+ }
1183
+ var init = {
1184
+ method: method,
1185
+ headers: headers,
1186
+ credentials: req.credentials,
1187
+ redirect: req.redirect,
1188
+ referrer: req.referrer,
1189
+ };
1190
+ if (req.mode && req.mode !== "navigate") init.mode = req.mode;
1191
+ if (body !== undefined) init.body = body;
1192
+ else if (method !== "GET" && method !== "HEAD") {
1193
+ try {
1194
+ init.body = await req.blob();
1195
+ } catch (e) {}
1196
+ }
1197
+ var res = await fetch(new Request(url, init));
1198
+ var resType = res.headers.get("content-type") || "";
1199
+ if (
1200
+ !/html|javascript|ecmascript|json|css|xml|svg|text|urlencoded/.test(resType)
1201
+ ) {
1202
+ return res;
1203
+ }
1204
+ var resText = await res.text();
1205
+ var mapped = rewriteText(resText);
1206
+ var outHeaders = new Headers(res.headers);
1207
+ outHeaders.delete("content-length");
1208
+ outHeaders.delete("content-encoding");
1209
+ return new Response(mapped, {
1210
+ status: res.status,
1211
+ statusText: res.statusText,
1212
+ headers: outHeaders,
1213
+ });
1214
+ })()
1215
+ );
1216
+ });
859
1217
  }
860
1218
 
861
1219
  function injectNextProxyShim(html, publicBase) {
862
1220
  const prefix = proxyPathPrefix(publicBase);
863
- if (
864
- !prefix ||
865
- html.includes("data-mp-proxy-next") ||
866
- (!isNextDocument(html) && !isViteDocument(html))
867
- ) {
1221
+ if (!prefix || html.includes("data-mp-proxy-next")) {
868
1222
  return html;
869
1223
  }
870
- const script = `<script data-mp-proxy-next>(${shareProxyShim.toString()})(${JSON.stringify(prefix)})</script>`;
871
- return html.replace(/<head([^>]*)>/i, `<head$1>${script}`);
1224
+ const script = `<script data-mp-proxy-next src="${prefix}/__mp/shim.js"><\/script>`;
1225
+ if (/<head[^>]*>/i.test(html)) {
1226
+ return html.replace(/<head([^>]*)>/i, `<head$1>${script}`);
1227
+ }
1228
+ if (/<body[^>]*>/i.test(html)) {
1229
+ return html.replace(/<body([^>]*)>/i, `<body$1>${script}`);
1230
+ }
1231
+ return `${script}${html}`;
872
1232
  }
873
1233
 
874
1234
  /**
@@ -885,6 +1245,7 @@ function injectNextProxyShim(html, publicBase) {
885
1245
  * acceptEncoding?: string,
886
1246
  * ifNoneMatch?: string,
887
1247
  * port?: number,
1248
+ * portUrls?: Record<string, string>,
888
1249
  * }} opts
889
1250
  * @returns {{ status: number, headers: Record<string, string>, body: Buffer }}
890
1251
  */
@@ -896,6 +1257,8 @@ export function processShareHttpResponse(opts) {
896
1257
  const acceptEncoding = String(opts?.acceptEncoding || "");
897
1258
  const ifNoneMatch = String(opts?.ifNoneMatch || "");
898
1259
  const port = Number(opts?.port) || 0;
1260
+ const portUrls =
1261
+ opts?.portUrls && typeof opts.portUrls === "object" ? opts.portUrls : {};
899
1262
  let status =
900
1263
  typeof opts?.status === "number" && opts.status >= 100 ? opts.status : 200;
901
1264
  const headers = lowerHeaders(opts?.headers || {});
@@ -903,12 +1266,7 @@ export function processShareHttpResponse(opts) {
903
1266
  ? opts.body
904
1267
  : Buffer.from(opts?.body || "");
905
1268
 
906
- if (headers.location) {
907
- headers.location = rewriteLocation(headers.location, publicBase, port);
908
- }
909
- if (headers.link) {
910
- headers.link = rewriteLinkHeader(headers.link, publicBase);
911
- }
1269
+ rewriteHeaderUrls(headers, publicBase, port, portUrls);
912
1270
 
913
1271
  const cachedKey = rewriteCacheKey(publicBase, path);
914
1272
  const hit =
@@ -933,10 +1291,20 @@ export function processShareHttpResponse(opts) {
933
1291
 
934
1292
  let text = payload.toString("utf8");
935
1293
  let mutated = false;
936
- if (publicBase && shouldRewriteBody(headers)) {
1294
+ const rewriteTextBody =
1295
+ shouldRewriteBody(headers) ||
1296
+ (!headerGet(headers, "content-type") && isProbablyUtf8Text(payload));
1297
+ if (publicBase && rewriteTextBody) {
937
1298
  text = prefixRootPaths(text, publicBase, headers["content-type"] || "");
938
1299
  mutated = true;
939
1300
  }
1301
+ if (Object.keys(portUrls).length && rewriteTextBody) {
1302
+ const mapped = rewriteMappedLocalUrls(text, portUrls);
1303
+ if (mapped !== text) {
1304
+ text = mapped;
1305
+ mutated = true;
1306
+ }
1307
+ }
940
1308
  if (aiPublicBase) {
941
1309
  const withShareUrls = rewriteLocalSidecarUrls(text, aiPublicBase, publicBase);
942
1310
  if (withShareUrls !== text) {
@@ -951,12 +1319,8 @@ export function processShareHttpResponse(opts) {
951
1319
  mutated = true;
952
1320
  }
953
1321
  }
954
- if (
955
- publicBase &&
956
- isHtmlDocument(headers, text) &&
957
- (isNextDocument(text) || isViteDocument(text))
958
- ) {
959
- const next = injectNextProxyShim(text, publicBase);
1322
+ if (publicBase && isHtmlDocument(headers, text)) {
1323
+ const next = injectNextProxyShim(text, publicBase, portUrls);
960
1324
  if (next !== text) {
961
1325
  text = next;
962
1326
  mutated = true;