remote-components 0.0.51 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/{component-loader-1838f572.d.ts → component-loader-21865da3.d.ts} +142 -16
  2. package/dist/host-config-58cdccea.d.ts +87 -0
  3. package/dist/html/host.cjs +589 -377
  4. package/dist/html/host.cjs.map +1 -1
  5. package/dist/html/host.d.ts +2 -0
  6. package/dist/html/host.js +588 -377
  7. package/dist/html/host.js.map +1 -1
  8. package/dist/html/remote.cjs +65 -57
  9. package/dist/html/remote.cjs.map +1 -1
  10. package/dist/html/remote.js +65 -57
  11. package/dist/html/remote.js.map +1 -1
  12. package/dist/internal/next/host/app-router-client.cjs +21 -10
  13. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  14. package/dist/internal/next/host/app-router-client.d.ts +36 -14
  15. package/dist/internal/next/host/app-router-client.js +21 -10
  16. package/dist/internal/next/host/app-router-client.js.map +1 -1
  17. package/dist/internal/next/remote/render-server.cjs.map +1 -1
  18. package/dist/internal/next/remote/render-server.d.ts +13 -14
  19. package/dist/internal/next/remote/render-server.js.map +1 -1
  20. package/dist/internal/react/context.cjs +43 -0
  21. package/dist/internal/react/context.cjs.map +1 -0
  22. package/dist/internal/react/context.d.ts +20 -0
  23. package/dist/internal/react/context.js +18 -0
  24. package/dist/internal/react/context.js.map +1 -0
  25. package/dist/internal/react/hooks/use-resolve-client-url.cjs +39 -0
  26. package/dist/internal/react/hooks/use-resolve-client-url.cjs.map +1 -0
  27. package/dist/internal/react/hooks/use-resolve-client-url.d.ts +5 -0
  28. package/dist/internal/react/hooks/use-resolve-client-url.js +15 -0
  29. package/dist/internal/react/hooks/use-resolve-client-url.js.map +1 -0
  30. package/dist/internal/shared/client/apply-origin.cjs +10 -5
  31. package/dist/internal/shared/client/apply-origin.cjs.map +1 -1
  32. package/dist/internal/shared/client/apply-origin.d.ts +3 -1
  33. package/dist/internal/shared/client/apply-origin.js +10 -5
  34. package/dist/internal/shared/client/apply-origin.js.map +1 -1
  35. package/dist/internal/shared/client/default-resolve-client-url.cjs +32 -0
  36. package/dist/internal/shared/client/default-resolve-client-url.cjs.map +1 -0
  37. package/dist/internal/shared/client/default-resolve-client-url.d.ts +5 -0
  38. package/dist/internal/shared/client/default-resolve-client-url.js +10 -0
  39. package/dist/internal/shared/client/default-resolve-client-url.js.map +1 -0
  40. package/dist/internal/shared/client/protected-rc-fallback.cjs +11 -2
  41. package/dist/internal/shared/client/protected-rc-fallback.cjs.map +1 -1
  42. package/dist/internal/shared/client/protected-rc-fallback.d.ts +2 -1
  43. package/dist/internal/shared/client/protected-rc-fallback.js +9 -1
  44. package/dist/internal/shared/client/protected-rc-fallback.js.map +1 -1
  45. package/dist/internal/shared/client/proxy-through-host.cjs +65 -0
  46. package/dist/internal/shared/client/proxy-through-host.cjs.map +1 -0
  47. package/dist/internal/shared/client/proxy-through-host.d.ts +62 -0
  48. package/dist/internal/shared/client/proxy-through-host.js +40 -0
  49. package/dist/internal/shared/client/proxy-through-host.js.map +1 -0
  50. package/dist/internal/shared/client/remote-component.cjs +121 -137
  51. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  52. package/dist/internal/shared/client/remote-component.d.ts +7 -5
  53. package/dist/internal/shared/client/remote-component.js +120 -137
  54. package/dist/internal/shared/client/remote-component.js.map +1 -1
  55. package/dist/internal/shared/constants.cjs +3 -0
  56. package/dist/internal/shared/constants.cjs.map +1 -1
  57. package/dist/internal/shared/constants.d.ts +2 -1
  58. package/dist/internal/shared/constants.js +2 -0
  59. package/dist/internal/shared/constants.js.map +1 -1
  60. package/dist/internal/shared/contract/host-state.cjs +38 -0
  61. package/dist/internal/shared/contract/host-state.cjs.map +1 -0
  62. package/dist/internal/shared/contract/host-state.d.ts +53 -0
  63. package/dist/internal/shared/contract/host-state.js +14 -0
  64. package/dist/internal/shared/contract/host-state.js.map +1 -0
  65. package/dist/internal/shared/contract/resolve-name-from-src.cjs +40 -0
  66. package/dist/internal/shared/contract/resolve-name-from-src.cjs.map +1 -0
  67. package/dist/internal/shared/contract/resolve-name-from-src.d.ts +13 -0
  68. package/dist/internal/shared/contract/resolve-name-from-src.js +16 -0
  69. package/dist/internal/shared/contract/resolve-name-from-src.js.map +1 -0
  70. package/dist/internal/shared/error.cjs +70 -0
  71. package/dist/internal/shared/error.cjs.map +1 -1
  72. package/dist/internal/shared/error.d.ts +3 -1
  73. package/dist/internal/shared/error.js +71 -0
  74. package/dist/internal/shared/error.js.map +1 -1
  75. package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
  76. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  77. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +1 -1
  78. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  79. package/dist/internal/shared/ssr/fetch-with-hooks.cjs +7 -2
  80. package/dist/internal/shared/ssr/fetch-with-hooks.cjs.map +1 -1
  81. package/dist/internal/shared/ssr/fetch-with-hooks.d.ts +1 -1
  82. package/dist/internal/shared/ssr/fetch-with-hooks.js +7 -2
  83. package/dist/internal/shared/ssr/fetch-with-hooks.js.map +1 -1
  84. package/dist/internal/shared/utils/logger.cjs +26 -10
  85. package/dist/internal/shared/utils/logger.cjs.map +1 -1
  86. package/dist/internal/shared/utils/logger.d.ts +6 -1
  87. package/dist/internal/shared/utils/logger.js +24 -9
  88. package/dist/internal/shared/utils/logger.js.map +1 -1
  89. package/dist/next/config.cjs +2 -2
  90. package/dist/next/config.cjs.map +1 -1
  91. package/dist/next/config.js +2 -2
  92. package/dist/next/config.js.map +1 -1
  93. package/dist/next/host/app-router-server.cjs.map +1 -1
  94. package/dist/next/host/app-router-server.d.ts +11 -41
  95. package/dist/next/host/app-router-server.js.map +1 -1
  96. package/dist/next/host/client/index.cjs +467 -298
  97. package/dist/next/host/client/index.cjs.map +1 -1
  98. package/dist/next/host/client/index.d.ts +3 -1
  99. package/dist/next/host/client/index.js +445 -277
  100. package/dist/next/host/client/index.js.map +1 -1
  101. package/dist/next/host/pages-router-client.cjs +15 -2
  102. package/dist/next/host/pages-router-client.cjs.map +1 -1
  103. package/dist/next/host/pages-router-client.d.ts +14 -26
  104. package/dist/next/host/pages-router-client.js +15 -2
  105. package/dist/next/host/pages-router-client.js.map +1 -1
  106. package/dist/next/host/pages-router-server.cjs +2 -0
  107. package/dist/next/host/pages-router-server.cjs.map +1 -1
  108. package/dist/next/host/pages-router-server.d.ts +17 -31
  109. package/dist/next/host/pages-router-server.js +2 -0
  110. package/dist/next/host/pages-router-server.js.map +1 -1
  111. package/dist/next/index.cjs.map +1 -1
  112. package/dist/next/index.d.ts +13 -39
  113. package/dist/next/index.js.map +1 -1
  114. package/dist/next/proxy.cjs +33 -6
  115. package/dist/next/proxy.cjs.map +1 -1
  116. package/dist/next/proxy.js +33 -6
  117. package/dist/next/proxy.js.map +1 -1
  118. package/dist/next/remote/server.d.ts +4 -0
  119. package/dist/proxy-through-host-a676a522.d.ts +52 -0
  120. package/dist/react/index.cjs +486 -298
  121. package/dist/react/index.cjs.map +1 -1
  122. package/dist/react/index.d.ts +27 -40
  123. package/dist/react/index.js +463 -277
  124. package/dist/react/index.js.map +1 -1
  125. package/dist/shared/host/proxy.cjs +32 -6
  126. package/dist/shared/host/proxy.cjs.map +1 -1
  127. package/dist/shared/host/proxy.js +36 -7
  128. package/dist/shared/host/proxy.js.map +1 -1
  129. package/dist/{types-cbe44b51.d.ts → types-2b26a246.d.ts} +23 -6
  130. package/package.json +1 -1
  131. package/dist/internal/shared/client/fetch-with-protected-rc-fallback.cjs +0 -65
  132. package/dist/internal/shared/client/fetch-with-protected-rc-fallback.cjs.map +0 -1
  133. package/dist/internal/shared/client/fetch-with-protected-rc-fallback.d.ts +0 -13
  134. package/dist/internal/shared/client/fetch-with-protected-rc-fallback.js +0 -41
  135. package/dist/internal/shared/client/fetch-with-protected-rc-fallback.js.map +0 -1
@@ -30,10 +30,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/react/index.tsx
31
31
  var react_exports = {};
32
32
  __export(react_exports, {
33
- RemoteComponent: () => RemoteComponent
33
+ RemoteComponent: () => RemoteComponent,
34
+ RemoteComponentsProvider: () => import_context2.RemoteComponentsProvider,
35
+ proxyClientRequestsThroughHost: () => proxyClientRequestsThroughHost
34
36
  });
35
37
  module.exports = __toCommonJS(react_exports);
36
- var import_react2 = require("react");
38
+ var import_react3 = require("react");
37
39
  var import_react_dom = require("react-dom");
38
40
 
39
41
  // src/shared/client/apply-origin.ts
@@ -48,7 +50,7 @@ var tagNames = [
48
50
  "script",
49
51
  "link"
50
52
  ];
51
- function applyOriginToNodes(doc, url) {
53
+ function applyOriginToNodes(doc, url, resolveClientUrl) {
52
54
  if (url.origin !== location.origin) {
53
55
  const nodes = doc.querySelectorAll(
54
56
  tagNames.map(
@@ -57,12 +59,15 @@ function applyOriginToNodes(doc, url) {
57
59
  );
58
60
  nodes.forEach((node) => {
59
61
  if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
60
- node.src = new URL(node.getAttribute("src") ?? "/", url).href;
62
+ const absoluteSrc = new URL(node.getAttribute("src") ?? "/", url).href;
63
+ const isScript = node.tagName.toLowerCase() === "script";
64
+ node.src = isScript ? absoluteSrc : resolveClientUrl?.(absoluteSrc) ?? absoluteSrc;
61
65
  }
62
66
  if (node.hasAttribute("href") && /^[./]+\/?/.test(node.getAttribute("href") ?? "")) {
67
+ const absoluteHref = new URL(node.getAttribute("href") ?? "/", url).href;
63
68
  node.setAttribute(
64
69
  "href",
65
- new URL(node.getAttribute("href") ?? "/", url).href
70
+ resolveClientUrl?.(absoluteHref) ?? absoluteHref
66
71
  );
67
72
  }
68
73
  if (node.hasAttribute("srcset")) {
@@ -71,7 +76,8 @@ function applyOriginToNodes(doc, url) {
71
76
  if (!urlPart)
72
77
  return entry;
73
78
  const absoluteUrl = new URL(urlPart, url).href;
74
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
79
+ const resolvedUrl = resolveClientUrl?.(absoluteUrl) ?? absoluteUrl;
80
+ return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl;
75
81
  }).join(", ");
76
82
  if (srcSet) {
77
83
  node.setAttribute("srcset", srcSet);
@@ -83,7 +89,8 @@ function applyOriginToNodes(doc, url) {
83
89
  if (!urlPart)
84
90
  return entry;
85
91
  const absoluteUrl = new URL(urlPart, url).href;
86
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
92
+ const resolvedUrl = resolveClientUrl?.(absoluteUrl) ?? absoluteUrl;
93
+ return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl;
87
94
  }).join(", ");
88
95
  if (srcSet) {
89
96
  node.setAttribute("imagesrcset", srcSet);
@@ -93,6 +100,34 @@ function applyOriginToNodes(doc, url) {
93
100
  }
94
101
  }
95
102
 
103
+ // src/shared/constants.ts
104
+ var RC_PROTECTED_REMOTE_FETCH_PATHNAME = "/rc-fetch-protected-remote";
105
+ var CORS_DOCS_URL = "https://vercel.com/docs/remote-components/concepts/cors-external-urls#accessing-cross-site-protected-remote-components";
106
+
107
+ // src/shared/client/protected-rc-fallback.ts
108
+ function generateProtectedRcFallbackSrc(url) {
109
+ return `${RC_PROTECTED_REMOTE_FETCH_PATHNAME}?url=${encodeURIComponent(url)}`;
110
+ }
111
+ function isProxiedUrl(url) {
112
+ try {
113
+ return new URL(url, location.href).pathname === RC_PROTECTED_REMOTE_FETCH_PATHNAME;
114
+ } catch {
115
+ return false;
116
+ }
117
+ }
118
+
119
+ // src/shared/utils/abort.ts
120
+ function isAbortError(error) {
121
+ if (error instanceof DOMException && error.name === "AbortError") {
122
+ return true;
123
+ }
124
+ if (error !== null && typeof error === "object" && "name" in error && error.name === "AbortError" && "message" in error && typeof error.message === "string") {
125
+ const e = error;
126
+ return typeof e.code === "number" || e.constructor?.name === "DOMException";
127
+ }
128
+ return false;
129
+ }
130
+
96
131
  // src/shared/error.ts
97
132
  var RemoteComponentsError = class extends Error {
98
133
  code = "REMOTE_COMPONENTS_ERROR";
@@ -112,6 +147,185 @@ function failedToFetchRemoteComponentError(url, { status, statusText }, help = "
112
147
  { cause: new Error(`${status} ${statusText}`) }
113
148
  );
114
149
  }
150
+ async function errorFromFailedFetch(originalUrl, resolvedUrl, res) {
151
+ const isProxied = isProxiedUrl(resolvedUrl.href);
152
+ if (isProxied && res) {
153
+ const body = await res.text().catch(() => "");
154
+ return failedProxyFetchError(
155
+ originalUrl,
156
+ resolvedUrl.href,
157
+ res.status,
158
+ body
159
+ );
160
+ }
161
+ const fallback = failedToFetchRemoteComponentError(
162
+ originalUrl,
163
+ res ?? { status: 0, statusText: "No Response" }
164
+ );
165
+ if (!res)
166
+ return fallback;
167
+ try {
168
+ const body = await res.text();
169
+ const parser = new DOMParser();
170
+ const doc = parser.parseFromString(body, "text/html");
171
+ const errorTemplate = doc.querySelector(
172
+ "template[data-next-error-message]"
173
+ );
174
+ const errorMessage = errorTemplate?.getAttribute("data-next-error-message");
175
+ if (errorMessage) {
176
+ const error = new RemoteComponentsError(errorMessage);
177
+ const errorStack = errorTemplate?.getAttribute("data-next-error-stack");
178
+ if (errorStack) {
179
+ error.stack = errorStack;
180
+ }
181
+ return error;
182
+ }
183
+ } catch (parseError) {
184
+ if (isAbortError(parseError))
185
+ throw parseError;
186
+ }
187
+ return fallback;
188
+ }
189
+ function failedProxyFetchError(originalUrl, proxyUrl, status, responseBody) {
190
+ if (status === 404) {
191
+ return new RemoteComponentsError(
192
+ `Could not proxy the request to "${originalUrl}" \u2014 the proxy endpoint "${RC_PROTECTED_REMOTE_FETCH_PATHNAME}" returned 404.
193
+
194
+ The host server needs middleware or a route that handles "${RC_PROTECTED_REMOTE_FETCH_PATHNAME}".
195
+
196
+ Proxying requires two pieces:
197
+ 1. resolveClientUrl={proxyClientRequestsThroughHost} on <RemoteComponent>
198
+ 2. Middleware or a route for "${RC_PROTECTED_REMOTE_FETCH_PATHNAME}" on the host server
199
+
200
+ Docs: ${CORS_DOCS_URL}`
201
+ );
202
+ }
203
+ if (status === 403) {
204
+ const detail = responseBody ? ` ${responseBody}` : "";
205
+ return new RemoteComponentsError(
206
+ `Proxied request to "${proxyUrl}" was forbidden.${detail} See: ${CORS_DOCS_URL}`
207
+ );
208
+ }
209
+ return new RemoteComponentsError(
210
+ `Proxied request for "${originalUrl}" via "${proxyUrl}" failed with status ${status}. See: ${CORS_DOCS_URL}`
211
+ );
212
+ }
213
+
214
+ // src/shared/utils/index.ts
215
+ function escapeString(str) {
216
+ return str.replace(/[^a-z0-9]/g, "_");
217
+ }
218
+ var attrToProp = {
219
+ fetchpriority: "fetchPriority",
220
+ crossorigin: "crossOrigin",
221
+ imagesrcset: "imageSrcSet",
222
+ imagesizes: "imageSizes",
223
+ srcset: "srcSet"
224
+ };
225
+
226
+ // src/shared/client/const.ts
227
+ var DEFAULT_ROUTE = "/";
228
+ var RUNTIME_WEBPACK = "webpack";
229
+ var RUNTIME_TURBOPACK = "turbopack";
230
+ var RUNTIME_SCRIPT = "script";
231
+ var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
232
+ function getBundleKey(bundle) {
233
+ return escapeString(bundle);
234
+ }
235
+
236
+ // src/shared/client/parse-remote-html.ts
237
+ function validateSingleComponent(doc, name, url) {
238
+ if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
239
+ throw multipleRemoteComponentsError(url);
240
+ }
241
+ }
242
+ function findComponentElement(doc, name) {
243
+ return doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? doc.querySelector("div[data-bundle][data-route]") ?? doc.querySelector("div#__next") ?? doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
244
+ }
245
+ function parseNextData(doc) {
246
+ return JSON.parse(
247
+ (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
248
+ );
249
+ }
250
+ function resolveComponentName(component, nextData, fallbackName) {
251
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
252
+ const name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component?.getAttribute("name") || (nextData ? "__next" : fallbackName);
253
+ return { name, isRemoteComponent };
254
+ }
255
+ function extractComponentMetadata(component, nextData, name, url) {
256
+ return {
257
+ name,
258
+ bundle: component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default",
259
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
260
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
261
+ };
262
+ }
263
+ function extractRemoteShared(doc, name, nextData) {
264
+ const remoteSharedEl = doc.querySelector(
265
+ `#${name}_shared[data-remote-components-shared]`
266
+ );
267
+ const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
268
+ remoteSharedEl?.remove();
269
+ return remoteShared;
270
+ }
271
+ function validateComponentFound(component, rsc, nextData, isRemoteComponent, url, name) {
272
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
273
+ throw new RemoteComponentsError(
274
+ `Remote Component not found on ${url}.${name !== "__vercel_remote_component" ? ` The name for the <RemoteComponent> is "${name}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
275
+ );
276
+ }
277
+ }
278
+ function extractLinks(doc, component) {
279
+ return Array.from(doc.querySelectorAll("link[href]")).filter(
280
+ (link) => !component.contains(link)
281
+ );
282
+ }
283
+ function extractScripts(doc, component, isRemoteComponent) {
284
+ return Array.from(
285
+ (isRemoteComponent ? component : doc).querySelectorAll(
286
+ "script[src],script[data-src]"
287
+ )
288
+ );
289
+ }
290
+ function parseRemoteComponentDocument(doc, name, url) {
291
+ validateSingleComponent(doc, name, url.href);
292
+ const component = findComponentElement(doc, name);
293
+ const nextData = parseNextData(doc);
294
+ const { name: resolvedName, isRemoteComponent } = resolveComponentName(
295
+ component,
296
+ nextData,
297
+ name
298
+ );
299
+ const rsc = doc.querySelector(`#${resolvedName}_rsc`);
300
+ const metadata = extractComponentMetadata(
301
+ component,
302
+ nextData,
303
+ resolvedName,
304
+ url
305
+ );
306
+ const remoteShared = extractRemoteShared(doc, resolvedName, nextData);
307
+ validateComponentFound(
308
+ component,
309
+ rsc,
310
+ nextData,
311
+ isRemoteComponent,
312
+ url.href,
313
+ resolvedName
314
+ );
315
+ const links = extractLinks(doc, component);
316
+ const scripts = extractScripts(doc, component, isRemoteComponent);
317
+ return {
318
+ component,
319
+ name: resolvedName,
320
+ isRemoteComponent,
321
+ metadata,
322
+ nextData,
323
+ rsc,
324
+ remoteShared,
325
+ links,
326
+ scripts
327
+ };
328
+ }
115
329
 
116
330
  // src/shared/utils/logger.ts
117
331
  var PREFIX = "remote-components";
@@ -121,9 +335,6 @@ function logDebug(location2, message) {
121
335
  console.debug(`[${PREFIX}:${location2}]: ${message}`);
122
336
  }
123
337
  }
124
- function logInfo(location2, message) {
125
- console.info(`[${PREFIX}:${location2}]: ${message}`);
126
- }
127
338
  function logWarn(location2, message) {
128
339
  console.warn(`[${PREFIX}:${location2}]: ${message}`);
129
340
  }
@@ -134,6 +345,19 @@ function logError(location2, message, cause) {
134
345
  })
135
346
  );
136
347
  }
348
+ function warnCrossOriginFetchError(logLocation, url) {
349
+ try {
350
+ const parsed = typeof url === "string" ? new URL(url) : url;
351
+ if (typeof location === "undefined" || parsed.origin === location.origin) {
352
+ return;
353
+ }
354
+ logWarn(
355
+ logLocation,
356
+ `Failed to fetch cross-origin resource "${parsed.href}". If this is a protected deployment, ensure withRemoteComponentsHost middleware is configured in your host and that the remote URL is included in allowedProxyUrls. See: ${CORS_DOCS_URL}`
357
+ );
358
+ } catch {
359
+ }
360
+ }
137
361
 
138
362
  // src/shared/client/polyfill.tsx
139
363
  var import_jsx_runtime = (
@@ -577,19 +801,11 @@ function createRSCStream(rscName, data) {
577
801
  });
578
802
  }
579
803
 
580
- // src/shared/constants.ts
581
- var RC_PROTECTED_REMOTE_FETCH_PATHNAME = "/rc-fetch-protected-remote";
582
-
583
- // src/shared/client/protected-rc-fallback.ts
584
- function generateProtectedRcFallbackSrc(url) {
585
- return `${RC_PROTECTED_REMOTE_FETCH_PATHNAME}?url=${encodeURIComponent(url)}`;
586
- }
587
-
588
804
  // src/shared/client/webpack-patterns.ts
589
805
  var NEXT_BUNDLE_PATH_RE = /\/_next\/\[.+\](?:%20| )/;
590
806
 
591
807
  // src/shared/client/script-loader.ts
592
- async function loadScripts(scripts) {
808
+ async function loadScripts(scripts, resolveClientUrl) {
593
809
  await Promise.all(
594
810
  scripts.map((script) => {
595
811
  return new Promise((resolve, reject) => {
@@ -598,117 +814,34 @@ async function loadScripts(scripts) {
598
814
  script.src.replace(NEXT_BUNDLE_PATH_RE, "/_next/"),
599
815
  location.origin
600
816
  ).href;
601
- const loadScriptWithProtectedRcFallback = (src, isFallback = false) => {
602
- const newScript = document.createElement("script");
603
- newScript.onload = () => {
604
- if (isFallback) {
605
- logInfo(
606
- "ScriptLoader",
607
- `Successfully loaded <script src="${newSrc}"> using fallback.`
608
- );
609
- }
610
- resolve();
611
- };
612
- newScript.onerror = () => {
613
- if (!isFallback) {
614
- const fallbackSrc = generateProtectedRcFallbackSrc(newSrc);
615
- logWarn(
616
- "ScriptLoader",
617
- `Failed to load <script src="${newSrc}"> for Remote Component. Trying fallback with ${RC_PROTECTED_REMOTE_FETCH_PATHNAME} (withRemoteComponentsHost)...`
618
- );
619
- loadScriptWithProtectedRcFallback(fallbackSrc, true);
620
- } else {
621
- logError(
622
- "ScriptLoader",
623
- `Failed to load fallback for <script src="${newSrc}"> for Remote Component.`
624
- );
625
- reject(
626
- new RemoteComponentsError(
627
- `Failed to load <script src="${newSrc}"> for Remote Component. Check the URL is correct.`
628
- )
629
- );
630
- }
631
- };
632
- newScript.src = src;
633
- newScript.async = true;
634
- document.head.appendChild(newScript);
817
+ const resolvedSrc = resolveClientUrl?.(newSrc) ?? newSrc;
818
+ const newScript = document.createElement("script");
819
+ newScript.onload = () => resolve();
820
+ newScript.onerror = () => {
821
+ const isProxied = isProxiedUrl(resolvedSrc);
822
+ if (isProxied) {
823
+ reject(
824
+ new RemoteComponentsError(
825
+ `Failed to load script "${newSrc}" via proxy "${resolvedSrc}". Ensure withRemoteComponentsHost middleware is configured and "${RC_PROTECTED_REMOTE_FETCH_PATHNAME}" is in the matcher. See: ${CORS_DOCS_URL}`
826
+ )
827
+ );
828
+ } else {
829
+ warnCrossOriginFetchError("ScriptLoader", newSrc);
830
+ reject(
831
+ new RemoteComponentsError(
832
+ `Failed to load <script src="${newSrc}"> for Remote Component. Check the URL is correct.`
833
+ )
834
+ );
835
+ }
635
836
  };
636
- loadScriptWithProtectedRcFallback(newSrc);
837
+ newScript.src = resolvedSrc;
838
+ newScript.async = true;
839
+ document.head.appendChild(newScript);
637
840
  });
638
841
  })
639
842
  );
640
843
  }
641
844
 
642
- // src/shared/utils/index.ts
643
- function escapeString(str) {
644
- return str.replace(/[^a-z0-9]/g, "_");
645
- }
646
- var attrToProp = {
647
- fetchpriority: "fetchPriority",
648
- crossorigin: "crossOrigin",
649
- imagesrcset: "imageSrcSet",
650
- imagesizes: "imageSizes",
651
- srcset: "srcSet"
652
- };
653
-
654
- // src/shared/client/const.ts
655
- var DEFAULT_ROUTE = "/";
656
- var RUNTIME_WEBPACK = "webpack";
657
- var RUNTIME_TURBOPACK = "turbopack";
658
- var RUNTIME_SCRIPT = "script";
659
- var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
660
- function getBundleKey(bundle) {
661
- return escapeString(bundle);
662
- }
663
-
664
- // src/shared/utils/abort.ts
665
- function isAbortError(error) {
666
- if (error instanceof DOMException && error.name === "AbortError") {
667
- return true;
668
- }
669
- if (error !== null && typeof error === "object" && "name" in error && error.name === "AbortError" && "message" in error && typeof error.message === "string") {
670
- const e = error;
671
- return typeof e.code === "number" || e.constructor?.name === "DOMException";
672
- }
673
- return false;
674
- }
675
-
676
- // src/shared/client/fetch-with-protected-rc-fallback.ts
677
- async function fetchWithProtectedRcFallback(url, init) {
678
- try {
679
- const res = await fetch(url, init);
680
- return res;
681
- } catch (error) {
682
- if (isAbortError(error)) {
683
- throw error;
684
- }
685
- const parsedUrl = new URL(url);
686
- if (typeof document === "object" && typeof document.location === "object" && document.location.origin !== parsedUrl.origin) {
687
- logWarn(
688
- "FetchRemoteComponent",
689
- "Request failed due to CORS, attempting to fetch it via the withRemoteComponentsHost proxy."
690
- );
691
- const proxiedRes = await fetch(
692
- generateProtectedRcFallbackSrc(parsedUrl.href),
693
- init?.signal ? { signal: init.signal } : void 0
694
- );
695
- if (proxiedRes.status === 200) {
696
- logInfo(
697
- "FetchRemoteComponent",
698
- `Successfully fetched ${parsedUrl.href} with fallback withRemoteComponentsHost proxy`
699
- );
700
- return proxiedRes;
701
- } else {
702
- logError(
703
- "FetchRemoteComponent",
704
- `Could not proxy remote: [response status ${proxiedRes.status}] ${await proxiedRes.text()}`
705
- );
706
- }
707
- }
708
- throw error;
709
- }
710
- }
711
-
712
845
  // src/shared/client/turbopack-patterns.ts
713
846
  var REMOTE_SHARED_MARKER_RE = /(?:self|[a-z])\.TURBOPACK_REMOTE_SHARED/;
714
847
  var REMOTE_SHARED_ASSIGNMENT_RE = /\.TURBOPACK_REMOTE_SHARED=await (?:__turbopack_context__|e)\.A\((?<sharedModuleId>[0-9]+)\)/;
@@ -718,7 +851,7 @@ var ASYNC_MODULE_ALL_RE = /(?<ctx>__turbopack_context__|e)=>\{\k<ctx>\.v\((?<vCb
718
851
  var TURBOPACK_GLOBAL_RE = /(?:globalThis|self)\s*(?:\.TURBOPACK|\[\s*["']TURBOPACK["']\s*\])/;
719
852
 
720
853
  // src/shared/client/chunk-loader.ts
721
- function createChunkLoader(runtime) {
854
+ function createChunkLoader(runtime, resolveClientUrl) {
722
855
  return function __turbopack_chunk_load__(chunkId, scriptBundle) {
723
856
  logDebug("ChunkLoader", `Loading chunk: "${chunkId}"`);
724
857
  const self = globalThis;
@@ -758,9 +891,10 @@ function createChunkLoader(runtime) {
758
891
  logDebug("ChunkLoader", `Returning cached promise for: "${url}"`);
759
892
  return self.__remote_components_turbopack_chunk_loader_promise__[url];
760
893
  }
761
- logDebug("ChunkLoader", `Fetching chunk from: "${url}"`);
894
+ const resolvedUrl = resolveClientUrl?.(url) ?? url;
895
+ logDebug("ChunkLoader", `Fetching chunk from: "${resolvedUrl}"`);
762
896
  self.__remote_components_turbopack_chunk_loader_promise__[url] = new Promise((resolve, reject) => {
763
- fetchWithProtectedRcFallback(url).then((res) => res.text()).then((code) => {
897
+ fetch(resolvedUrl).then((res) => res.text()).then((code) => {
764
898
  const hasTurbopack = TURBOPACK_GLOBAL_RE.test(code);
765
899
  if (hasTurbopack) {
766
900
  return handleTurbopackChunk(code, bundle ?? "", url);
@@ -773,7 +907,19 @@ function createChunkLoader(runtime) {
773
907
  "ChunkLoader",
774
908
  `First 500 chars of chunk: ${code.slice(0, 500)}`
775
909
  );
776
- }).then(resolve).catch(reject);
910
+ }).then(resolve).catch((error) => {
911
+ const isProxied = isProxiedUrl(resolvedUrl);
912
+ if (isProxied) {
913
+ reject(
914
+ new RemoteComponentsError(
915
+ `Failed to load chunk "${url}" via proxy "${resolvedUrl}". Ensure withRemoteComponentsHost middleware is configured and "${RC_PROTECTED_REMOTE_FETCH_PATHNAME}" is in the matcher. See: ${CORS_DOCS_URL}`
916
+ )
917
+ );
918
+ } else {
919
+ warnCrossOriginFetchError("ChunkLoader", url);
920
+ reject(error);
921
+ }
922
+ });
777
923
  });
778
924
  return self.__remote_components_turbopack_chunk_loader_promise__[url];
779
925
  };
@@ -1266,7 +1412,7 @@ function getSharedModule(bundle, id) {
1266
1412
  }
1267
1413
 
1268
1414
  // src/shared/client/webpack-adapter.ts
1269
- async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location.href), bundle, shared = {}, remoteShared = {}) {
1415
+ async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location.href), bundle, shared = {}, remoteShared = {}, resolveClientUrl) {
1270
1416
  const self = globalThis;
1271
1417
  if (!self.__remote_bundle_url__) {
1272
1418
  self.__remote_bundle_url__ = {};
@@ -1278,7 +1424,7 @@ async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location
1278
1424
  self.__original_webpack_chunk_load__ = self.__webpack_chunk_load__;
1279
1425
  self.__original_webpack_require__ = self.__webpack_require__;
1280
1426
  }
1281
- self.__webpack_chunk_load__ = createChunkLoader(runtime);
1427
+ self.__webpack_chunk_load__ = createChunkLoader(runtime, resolveClientUrl);
1282
1428
  self.__webpack_require__ = createModuleRequire(runtime);
1283
1429
  self.__webpack_require_type__ = runtime;
1284
1430
  if (self.__remote_webpack_require__ && runtime === RUNTIME_TURBOPACK) {
@@ -1373,7 +1519,8 @@ async function loadRemoteComponent({
1373
1519
  scripts = [],
1374
1520
  shared = Promise.resolve({}),
1375
1521
  remoteShared = {},
1376
- container
1522
+ container,
1523
+ resolveClientUrl
1377
1524
  }) {
1378
1525
  try {
1379
1526
  if (runtime === "webpack") {
@@ -1382,7 +1529,7 @@ async function loadRemoteComponent({
1382
1529
  self.__DISABLE_WEBPACK_EXEC__ = {};
1383
1530
  }
1384
1531
  self.__DISABLE_WEBPACK_EXEC__[bundle] = true;
1385
- await loadScripts(scripts);
1532
+ await loadScripts(scripts, resolveClientUrl);
1386
1533
  }
1387
1534
  const hostShared = await shared;
1388
1535
  logDebug(
@@ -1403,7 +1550,8 @@ async function loadRemoteComponent({
1403
1550
  url,
1404
1551
  bundle,
1405
1552
  hostShared,
1406
- remoteShared
1553
+ remoteShared,
1554
+ resolveClientUrl
1407
1555
  );
1408
1556
  if (bundle) {
1409
1557
  const resolve = {
@@ -1492,6 +1640,42 @@ function loadNextPagesComponent(bundle, route, nextData, name, container) {
1492
1640
  return { component };
1493
1641
  }
1494
1642
 
1643
+ // src/shared/client/proxy-through-host.ts
1644
+ function withRemoteSrc(resolveClientUrl, remoteSrc) {
1645
+ const remoteOrigin = parseOrigin(remoteSrc);
1646
+ return (url) => {
1647
+ const urlOrigin = parseOrigin(url);
1648
+ if (remoteOrigin && urlOrigin && urlOrigin !== remoteOrigin) {
1649
+ return void 0;
1650
+ }
1651
+ return resolveClientUrl(remoteSrc, url);
1652
+ };
1653
+ }
1654
+ function parseOrigin(url) {
1655
+ try {
1656
+ return new URL(url).origin;
1657
+ } catch {
1658
+ return void 0;
1659
+ }
1660
+ }
1661
+ var proxyClientRequestsThroughHost = (remoteSrc, url) => {
1662
+ if (typeof location === "undefined") {
1663
+ return void 0;
1664
+ }
1665
+ const remoteOrigin = new URL(remoteSrc, location.href).origin;
1666
+ if (remoteOrigin === location.origin) {
1667
+ return void 0;
1668
+ }
1669
+ try {
1670
+ const parsed = new URL(url, location.href);
1671
+ if (parsed.origin === remoteOrigin) {
1672
+ return generateProtectedRcFallbackSrc(url);
1673
+ }
1674
+ } catch {
1675
+ }
1676
+ return void 0;
1677
+ };
1678
+
1495
1679
  // src/shared/client/set-attributes-from-props.ts
1496
1680
  var DOMAttributeNames = {
1497
1681
  acceptCharset: "accept-charset",
@@ -1535,27 +1719,21 @@ function setAttributesFromProps(el, props) {
1535
1719
  }
1536
1720
 
1537
1721
  // src/shared/client/static-loader.ts
1538
- async function importViaProxy(absoluteSrc) {
1539
- const proxyUrl = new URL(
1540
- generateProtectedRcFallbackSrc(absoluteSrc),
1541
- location.href
1542
- ).href;
1543
- const response = await fetch(proxyUrl);
1722
+ async function importViaCallback(absoluteSrc, resolveClientUrl) {
1723
+ const resolvedUrl = resolveClientUrl(absoluteSrc) ?? absoluteSrc;
1724
+ const fetchUrl = new URL(resolvedUrl, location.href).href;
1725
+ const response = await fetch(fetchUrl);
1544
1726
  if (!response.ok)
1545
- throw new Error(`Proxy fetch failed: ${response.status}`);
1546
- logInfo(
1547
- "StaticLoader",
1548
- `Successfully loaded ${absoluteSrc} via protected RC proxy fallback.`
1549
- );
1727
+ throw new Error(`Proxied fetch failed: ${response.status}`);
1550
1728
  const content = (await response.text()).replace(/import\.meta\.url/g, JSON.stringify(absoluteSrc)).replace(
1551
1729
  /\b(from|import)\s*(["'])(\.\.?\/[^"']+)\2/g,
1552
1730
  (_, keyword, quote, relativePath) => {
1553
1731
  const absoluteImportUrl = new URL(relativePath, absoluteSrc).href;
1554
- const absoluteProxyUrl = new URL(
1555
- generateProtectedRcFallbackSrc(absoluteImportUrl),
1732
+ const resolvedImportUrl = new URL(
1733
+ resolveClientUrl(absoluteImportUrl) ?? absoluteImportUrl,
1556
1734
  location.href
1557
1735
  ).href;
1558
- return `${keyword} ${quote}${absoluteProxyUrl}${quote}`;
1736
+ return `${keyword} ${quote}${resolvedImportUrl}${quote}`;
1559
1737
  }
1560
1738
  );
1561
1739
  const moduleBlobUrl = URL.createObjectURL(
@@ -1589,6 +1767,20 @@ async function importViaProxy(absoluteSrc) {
1589
1767
  delete registry[absoluteSrc];
1590
1768
  return mod;
1591
1769
  }
1770
+ async function importDirectly(absoluteSrc) {
1771
+ try {
1772
+ return await import(
1773
+ /* @vite-ignore */
1774
+ /* webpackIgnore: true */
1775
+ absoluteSrc
1776
+ );
1777
+ } catch (importError) {
1778
+ if (!absoluteSrc.startsWith("blob:")) {
1779
+ warnCrossOriginFetchError("StaticLoader", absoluteSrc);
1780
+ }
1781
+ throw importError;
1782
+ }
1783
+ }
1592
1784
  function resolveScriptSrc(script, url) {
1593
1785
  const rawSrc = typeof script.getAttribute === "function" ? script.getAttribute("src") ?? script.src : script.src;
1594
1786
  if (!rawSrc && script.textContent) {
@@ -1601,24 +1793,7 @@ function resolveScriptSrc(script, url) {
1601
1793
  }
1602
1794
  return rawSrc;
1603
1795
  }
1604
- async function importScriptMod(absoluteSrc) {
1605
- try {
1606
- return await import(
1607
- /* @vite-ignore */
1608
- /* webpackIgnore: true */
1609
- absoluteSrc
1610
- );
1611
- } catch (importError) {
1612
- if (absoluteSrc.startsWith("blob:"))
1613
- throw importError;
1614
- logWarn(
1615
- "StaticLoader",
1616
- `Direct import of ${absoluteSrc} failed, attempting via protected RC proxy fallback.`
1617
- );
1618
- return importViaProxy(absoluteSrc);
1619
- }
1620
- }
1621
- async function loadStaticRemoteComponent(scripts, url) {
1796
+ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
1622
1797
  const self = globalThis;
1623
1798
  if (self.__remote_script_entrypoint_mount__?.[url.href]) {
1624
1799
  self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
@@ -1631,7 +1806,7 @@ async function loadStaticRemoteComponent(scripts, url) {
1631
1806
  try {
1632
1807
  const src = resolveScriptSrc(script, url);
1633
1808
  const absoluteSrc = new URL(src, url).href;
1634
- const mod = await importScriptMod(absoluteSrc);
1809
+ const mod = resolveClientUrl ? await importViaCallback(absoluteSrc, resolveClientUrl) : await importDirectly(absoluteSrc);
1635
1810
  if (src.startsWith("blob:")) {
1636
1811
  URL.revokeObjectURL(src);
1637
1812
  }
@@ -1693,6 +1868,32 @@ async function loadStaticRemoteComponent(scripts, url) {
1693
1868
  );
1694
1869
  }
1695
1870
 
1871
+ // src/shared/contract/host-state.ts
1872
+ function createHostState() {
1873
+ return {
1874
+ stage: "idle",
1875
+ prevSrc: void 0,
1876
+ prevUrl: void 0,
1877
+ prevName: void 0,
1878
+ prevIsRemoteComponent: false,
1879
+ abortController: void 0
1880
+ };
1881
+ }
1882
+
1883
+ // src/shared/contract/resolve-name-from-src.ts
1884
+ function resolveNameFromSrc(src, defaultName) {
1885
+ if (!src) {
1886
+ return defaultName;
1887
+ }
1888
+ const hash = typeof src === "string" ? src : src.hash;
1889
+ const hashIndex = hash.indexOf("#");
1890
+ if (hashIndex < 0) {
1891
+ return defaultName;
1892
+ }
1893
+ const name = hash.slice(hashIndex + 1);
1894
+ return name || defaultName;
1895
+ }
1896
+
1696
1897
  // src/shared/ssr/fetch-headers.ts
1697
1898
  function remoteFetchHeaders() {
1698
1899
  return {
@@ -1729,7 +1930,12 @@ async function fetchWithHooks(url, additionalInit, options = {}) {
1729
1930
  };
1730
1931
  let res = await onRequest?.(url, init, hookOptions);
1731
1932
  if (!res) {
1732
- res = await fetchWithProtectedRcFallback(url, init);
1933
+ try {
1934
+ res = await fetch(url, init);
1935
+ } catch (error) {
1936
+ warnCrossOriginFetchError("FetchRemoteComponent", url);
1937
+ throw error;
1938
+ }
1733
1939
  }
1734
1940
  const transformedRes = await onResponse?.(url, res, hookOptions);
1735
1941
  if (transformedRes) {
@@ -1747,15 +1953,34 @@ function getClientOrServerUrl(src, serverFallback) {
1747
1953
  return typeof src === "string" ? new URL(src, fallback) : src;
1748
1954
  }
1749
1955
 
1750
- // src/react/hooks/use-shadow-root.ts
1956
+ // src/react/hooks/use-resolve-client-url.ts
1751
1957
  var import_react = require("react");
1958
+ var import_context = require("#internal/react/context");
1959
+
1960
+ // src/shared/client/default-resolve-client-url.ts
1961
+ function bindResolveClientUrl(prop, remoteSrc) {
1962
+ return prop ? withRemoteSrc(prop, remoteSrc) : void 0;
1963
+ }
1964
+
1965
+ // src/react/hooks/use-resolve-client-url.ts
1966
+ function useResolveClientUrl(prop, urlHref) {
1967
+ const { resolveClientUrl: contextValue } = (0, import_context.useRemoteComponentsContext)();
1968
+ const resolveClientUrl = prop ?? contextValue;
1969
+ return (0, import_react.useMemo)(
1970
+ () => bindResolveClientUrl(resolveClientUrl, urlHref),
1971
+ [resolveClientUrl, urlHref]
1972
+ );
1973
+ }
1974
+
1975
+ // src/react/hooks/use-shadow-root.ts
1976
+ var import_react2 = require("react");
1752
1977
  function useShadowRoot({
1753
1978
  isolate,
1754
1979
  mode,
1755
1980
  keySuffix
1756
1981
  }) {
1757
- const shadowRootContainerRef = (0, import_react.useRef)(null);
1758
- const [shadowRoot, setShadowRoot] = (0, import_react.useState)(() => {
1982
+ const shadowRootContainerRef = (0, import_react2.useRef)(null);
1983
+ const [shadowRoot, setShadowRoot] = (0, import_react2.useState)(() => {
1759
1984
  const self = globalThis;
1760
1985
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1761
1986
  const ssrShadowRoot = typeof document !== "undefined" ? document.querySelector(
@@ -1764,7 +1989,7 @@ function useShadowRoot({
1764
1989
  self[shadowRootKey] = null;
1765
1990
  return ssrShadowRoot;
1766
1991
  });
1767
- (0, import_react.useLayoutEffect)(() => {
1992
+ (0, import_react2.useLayoutEffect)(() => {
1768
1993
  if (isolate !== false && typeof document !== "undefined" && (!shadowRoot || !shadowRoot.isConnected)) {
1769
1994
  const self = globalThis;
1770
1995
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
@@ -1796,7 +2021,7 @@ function useShadowRoot({
1796
2021
  return { shadowRoot, shadowRootContainerRef };
1797
2022
  }
1798
2023
 
1799
- // src/react/utils/parse-remote-html.ts
2024
+ // src/react/utils/extract-remote-html.ts
1800
2025
  var DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
1801
2026
  function getRemoteComponentHtml(html) {
1802
2027
  if (typeof document === "undefined")
@@ -1819,11 +2044,12 @@ function getRemoteComponentHtml(html) {
1819
2044
  }
1820
2045
 
1821
2046
  // src/react/index.tsx
2047
+ var import_context2 = require("#internal/react/context");
1822
2048
  var import_jsx_runtime2 = (
1823
2049
  // TODO: remove wrapper div by converting HTML to RSC or React tree
1824
2050
  require("react/jsx-runtime")
1825
2051
  );
1826
- var import_react3 = require("react");
2052
+ var import_react4 = require("react");
1827
2053
  function RemoteComponent({
1828
2054
  src,
1829
2055
  isolate,
@@ -1838,40 +2064,34 @@ function RemoteComponent({
1838
2064
  onError,
1839
2065
  onChange,
1840
2066
  onRequest,
1841
- onResponse
2067
+ onResponse,
2068
+ resolveClientUrl: _resolveClientUrl
1842
2069
  }) {
1843
- const instanceId = (0, import_react2.useId)();
1844
- const name = (0, import_react2.useMemo)(() => {
1845
- if (typeof src === "string") {
1846
- const url2 = new URL(
1847
- src,
1848
- typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
1849
- );
1850
- if (url2.hash) {
1851
- return url2.hash.slice(1);
1852
- }
1853
- } else if (typeof src === "object" && "hash" in src && src.hash) {
1854
- return src.hash.slice(1) || nameProp;
1855
- }
1856
- return nameProp;
1857
- }, [src, nameProp]);
1858
- const [data, setData] = (0, import_react2.useState)(null);
1859
- const url = (0, import_react2.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
2070
+ const instanceId = (0, import_react3.useId)();
2071
+ const name = (0, import_react3.useMemo)(
2072
+ () => resolveNameFromSrc(src, nameProp),
2073
+ [src, nameProp]
2074
+ );
2075
+ const [data, setData] = (0, import_react3.useState)(null);
2076
+ const url = (0, import_react3.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
2077
+ const resolveClientUrl = useResolveClientUrl(_resolveClientUrl, url.href);
1860
2078
  const id = url.origin === (typeof location !== "undefined" ? location.origin : DUMMY_FALLBACK) ? url.pathname : url.href;
1861
- const keySuffix = `${escapeString(id)}_${escapeString(data?.name ?? name)}_${escapeString(instanceId)}`;
1862
- const [remoteComponent, setRemoteComponent] = (0, import_react2.useState)(null);
2079
+ const keySuffix = `${escapeString(id)}_${escapeString(
2080
+ data?.name ?? name
2081
+ )}_${escapeString(instanceId)}`;
2082
+ const [remoteComponent, setRemoteComponent] = (0, import_react3.useState)(null);
1863
2083
  const { shadowRoot, shadowRootContainerRef } = useShadowRoot({
1864
2084
  isolate,
1865
2085
  mode,
1866
2086
  keySuffix
1867
2087
  });
1868
- const htmlRef = (0, import_react2.useRef)(
2088
+ const htmlRef = (0, import_react3.useRef)(
1869
2089
  typeof document !== "undefined" ? document.querySelector(
1870
2090
  `[data-remote-component-id="shadowroot_${keySuffix}"]`
1871
2091
  )?.shadowRoot?.innerHTML ?? document.getElementById(`__REMOTE_COMPONENT${name}`)?.innerHTML ?? document.querySelector(`div[data-bundle][data-route][id^="${name}"]`)?.innerHTML ?? document.querySelector("div[data-bundle][data-route]")?.innerHTML : null
1872
2092
  );
1873
- const endTemplateRef = (0, import_react2.useRef)(null);
1874
- const childrenRef = (0, import_react2.useRef)(
2093
+ const endTemplateRef = (0, import_react3.useRef)(null);
2094
+ const childrenRef = (0, import_react3.useRef)(
1875
2095
  typeof document !== "undefined" ? (() => {
1876
2096
  let el = document.querySelector(`template[id="${name}_start"]`);
1877
2097
  const elements = [];
@@ -1884,20 +2104,17 @@ function RemoteComponent({
1884
2104
  return elements;
1885
2105
  })() : []
1886
2106
  );
1887
- const prevSrcRef = (0, import_react2.useRef)(null);
1888
- const componentHydrationHtml = (0, import_react2.useRef)(null);
1889
- const prevIsRemoteComponentRef = (0, import_react2.useRef)(false);
1890
- const prevUrlRef = (0, import_react2.useRef)(null);
1891
- const prevRemoteComponentContainerRef = (0, import_react2.useRef)(null);
1892
- const unmountRef = (0, import_react2.useRef)(null);
1893
- const prevNameRef = (0, import_react2.useRef)(void 0);
1894
- (0, import_react2.useLayoutEffect)(() => {
2107
+ const hostStateRef = (0, import_react3.useRef)(createHostState());
2108
+ const componentHydrationHtml = (0, import_react3.useRef)(null);
2109
+ const prevRemoteComponentContainerRef = (0, import_react3.useRef)(null);
2110
+ const unmountRef = (0, import_react3.useRef)(null);
2111
+ (0, import_react3.useLayoutEffect)(() => {
1895
2112
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1896
2113
  return () => {
1897
2114
  delete globalThis[shadowRootKey];
1898
2115
  };
1899
2116
  }, [keySuffix]);
1900
- (0, import_react2.useLayoutEffect)(() => {
2117
+ (0, import_react3.useLayoutEffect)(() => {
1901
2118
  if (childrenRef.current.length > 0 && remoteComponent) {
1902
2119
  childrenRef.current.forEach((el) => {
1903
2120
  el.remove();
@@ -1905,7 +2122,7 @@ function RemoteComponent({
1905
2122
  childrenRef.current = [];
1906
2123
  }
1907
2124
  }, [remoteComponent]);
1908
- (0, import_react2.useLayoutEffect)(() => {
2125
+ (0, import_react3.useLayoutEffect)(() => {
1909
2126
  if (shadowRoot && remoteComponent) {
1910
2127
  const resetStyles = shadowRoot.querySelectorAll(
1911
2128
  "style[data-remote-components-reset]"
@@ -1928,16 +2145,20 @@ function RemoteComponent({
1928
2145
  }
1929
2146
  }
1930
2147
  }, [shadowRoot, remoteComponent, name]);
1931
- (0, import_react2.useEffect)(() => {
1932
- if (src && src !== prevSrcRef.current) {
1933
- const previousSrc = prevSrcRef.current;
1934
- const previousName = prevNameRef.current;
1935
- prevSrcRef.current = src;
2148
+ (0, import_react3.useEffect)(() => {
2149
+ if (src && src !== hostStateRef.current.prevSrc) {
2150
+ const previousSrc = hostStateRef.current.prevSrc;
2151
+ const previousName = hostStateRef.current.prevName;
2152
+ hostStateRef.current.prevSrc = src;
1936
2153
  if (previousSrc !== null) {
1937
2154
  htmlRef.current = null;
1938
2155
  }
2156
+ hostStateRef.current.abortController?.abort();
2157
+ hostStateRef.current.abortController = new AbortController();
2158
+ const { signal } = hostStateRef.current.abortController;
1939
2159
  onBeforeLoad?.(src);
1940
- (0, import_react2.startTransition)(async () => {
2160
+ hostStateRef.current.stage = "loading";
2161
+ (0, import_react3.startTransition)(async () => {
1941
2162
  try {
1942
2163
  let html = getRemoteComponentHtml(
1943
2164
  htmlRef.current ?? (endTemplateRef.current?.previousElementSibling?.tagName === "div" ? endTemplateRef.current.previousElementSibling.innerHTML : "")
@@ -1946,86 +2167,45 @@ function RemoteComponent({
1946
2167
  const fetchInit = {
1947
2168
  credentials
1948
2169
  };
1949
- const abortController = new AbortController();
1950
- const res = await fetchWithHooks(url, fetchInit, {
2170
+ const resolvedUrl = new URL(
2171
+ resolveClientUrl?.(url.href) ?? url.href,
2172
+ location.href
2173
+ );
2174
+ const res = await fetchWithHooks(resolvedUrl, fetchInit, {
1951
2175
  onRequest,
1952
2176
  onResponse,
1953
- abortController
2177
+ abortController: hostStateRef.current.abortController
1954
2178
  });
1955
2179
  if (!res || !res.ok) {
1956
- let error = failedToFetchRemoteComponentError(
1957
- url.href,
1958
- res ?? new Response(null, { status: 0 })
1959
- );
1960
- try {
1961
- const body = await res.text();
1962
- const parser2 = new DOMParser();
1963
- const doc2 = parser2.parseFromString(body, "text/html");
1964
- const errorTemplate = doc2.querySelector(
1965
- "template[data-next-error-message]"
1966
- );
1967
- const errorMessage = errorTemplate?.getAttribute(
1968
- "data-next-error-message"
1969
- );
1970
- const errorStack = errorTemplate?.getAttribute(
1971
- "data-next-error-stack"
1972
- );
1973
- if (errorMessage) {
1974
- error = new RemoteComponentsError(errorMessage);
1975
- if (errorStack) {
1976
- error.stack = errorStack;
1977
- }
1978
- }
1979
- } catch (parseError) {
1980
- if (isAbortError(parseError))
1981
- throw parseError;
1982
- }
1983
- throw error;
2180
+ throw await errorFromFailedFetch(url.href, resolvedUrl, res);
1984
2181
  }
1985
2182
  const remoteHtml = await res.text();
2183
+ if (signal.aborted)
2184
+ return;
1986
2185
  htmlRef.current = remoteHtml;
1987
2186
  html = getRemoteComponentHtml(remoteHtml);
1988
2187
  }
2188
+ if (signal.aborted)
2189
+ return;
1989
2190
  const parser = new DOMParser();
1990
2191
  const doc = parser.parseFromString(html, "text/html");
1991
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
1992
- `div[data-bundle][data-route][id^="${name}"]`
1993
- ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
1994
- throw multipleRemoteComponentsError(url.href);
1995
- }
1996
- const component = doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
1997
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
1998
- doc.querySelector("div#__next") ?? // fallback to the remote-component web component
1999
- doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2000
- const nextData = JSON.parse(
2001
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2002
- );
2003
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
2004
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
2005
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
2006
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2007
- const metadata = {
2192
+ const {
2193
+ component,
2008
2194
  name: remoteName,
2009
- bundle,
2010
- route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
2011
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
2012
- };
2013
- const remoteSharedEl = doc.querySelector(
2014
- `#${remoteName}_shared[data-remote-components-shared]`
2015
- );
2016
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2017
- remoteSharedEl?.remove();
2018
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2019
- throw new RemoteComponentsError(
2020
- `Remote Component not found on ${url.href}.${remoteName !== "__vercel_remote_component" ? `The name for the <RemoteComponent> is "${remoteName}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
2021
- );
2022
- }
2023
- if (prevIsRemoteComponentRef.current) {
2195
+ isRemoteComponent,
2196
+ metadata,
2197
+ nextData,
2198
+ rsc,
2199
+ remoteShared,
2200
+ links: linkElements,
2201
+ scripts: scriptElements
2202
+ } = parseRemoteComponentDocument(doc, name, url);
2203
+ if (hostStateRef.current.prevIsRemoteComponent) {
2024
2204
  if (shadowRoot) {
2025
2205
  shadowRoot.innerHTML = "";
2026
2206
  }
2027
2207
  const self = globalThis;
2028
- const prevUrl = prevUrlRef.current;
2208
+ const prevUrl = hostStateRef.current.prevUrl;
2029
2209
  if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2030
2210
  const unmountPromises = Promise.all(
2031
2211
  Array.from(unmountRef.current ?? []).map(
@@ -2038,15 +2218,11 @@ function RemoteComponent({
2038
2218
  await unmountPromises;
2039
2219
  }
2040
2220
  }
2041
- prevIsRemoteComponentRef.current = isRemoteComponent;
2042
- prevUrlRef.current = url;
2043
- prevNameRef.current = remoteName;
2044
- applyOriginToNodes(doc, url);
2045
- const links = Array.from(
2046
- doc.querySelectorAll("link[href]")
2047
- ).filter((link) => {
2048
- return !component.contains(link);
2049
- }).map((link) => ({
2221
+ hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2222
+ hostStateRef.current.prevUrl = url;
2223
+ hostStateRef.current.prevName = remoteName;
2224
+ applyOriginToNodes(doc, url, resolveClientUrl);
2225
+ const links = linkElements.map((link) => ({
2050
2226
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2051
2227
  ...link.getAttributeNames().reduce((acc, key) => {
2052
2228
  if (key !== "href") {
@@ -2055,7 +2231,7 @@ function RemoteComponent({
2055
2231
  return acc;
2056
2232
  }, {})
2057
2233
  }));
2058
- const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
2234
+ const scripts = scriptElements;
2059
2235
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2060
2236
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2061
2237
  );
@@ -2146,7 +2322,7 @@ function RemoteComponent({
2146
2322
  );
2147
2323
  }
2148
2324
  if (isRemoteComponent) {
2149
- if (previousSrc !== null) {
2325
+ if (previousSrc !== void 0) {
2150
2326
  onChange?.({
2151
2327
  previousSrc,
2152
2328
  nextSrc: src,
@@ -2165,7 +2341,8 @@ function RemoteComponent({
2165
2341
  setRemoteComponent(null);
2166
2342
  const { mount, unmount } = await loadStaticRemoteComponent(
2167
2343
  Array.from(shadowRoot.querySelectorAll("script")),
2168
- url
2344
+ url,
2345
+ resolveClientUrl
2169
2346
  );
2170
2347
  unmountRef.current = unmount;
2171
2348
  await Promise.all(
@@ -2185,7 +2362,8 @@ function RemoteComponent({
2185
2362
  htmlRef.current = null;
2186
2363
  const { mount, unmount } = await loadStaticRemoteComponent(
2187
2364
  Array.from(component.querySelectorAll("script")),
2188
- url
2365
+ url,
2366
+ resolveClientUrl
2189
2367
  );
2190
2368
  unmountRef.current = unmount;
2191
2369
  await Promise.all(
@@ -2195,12 +2373,13 @@ function RemoteComponent({
2195
2373
  );
2196
2374
  onLoad?.(src);
2197
2375
  }
2376
+ hostStateRef.current.stage = "loaded";
2198
2377
  } else {
2199
2378
  const result = await loadRemoteComponent({
2200
2379
  url,
2201
2380
  name: remoteName,
2202
2381
  rscName,
2203
- bundle,
2382
+ bundle: metadata.bundle,
2204
2383
  route: metadata.route,
2205
2384
  runtime: metadata.runtime,
2206
2385
  data: newData.data,
@@ -2228,13 +2407,14 @@ function RemoteComponent({
2228
2407
  ...userShared
2229
2408
  },
2230
2409
  remoteShared,
2231
- container: shadowRoot
2410
+ container: shadowRoot,
2411
+ resolveClientUrl
2232
2412
  });
2233
2413
  if (rsc) {
2234
2414
  rsc.remove();
2235
2415
  }
2236
2416
  setData(newData);
2237
- if (previousSrc !== null) {
2417
+ if (previousSrc !== void 0) {
2238
2418
  onChange?.({
2239
2419
  previousSrc,
2240
2420
  nextSrc: src,
@@ -2243,17 +2423,21 @@ function RemoteComponent({
2243
2423
  });
2244
2424
  }
2245
2425
  if (result.error) {
2426
+ hostStateRef.current.stage = "error";
2246
2427
  setRemoteComponent(result.error);
2247
2428
  onError?.(result.error);
2248
2429
  } else {
2430
+ hostStateRef.current.stage = "loaded";
2249
2431
  setRemoteComponent(result.component);
2250
2432
  onLoad?.(src);
2251
2433
  }
2252
2434
  }
2253
2435
  } catch (error) {
2254
2436
  if (isAbortError(error)) {
2437
+ hostStateRef.current.stage = "idle";
2255
2438
  return;
2256
2439
  }
2440
+ hostStateRef.current.stage = "error";
2257
2441
  setRemoteComponent(error);
2258
2442
  onError?.(error);
2259
2443
  }
@@ -2274,7 +2458,8 @@ function RemoteComponent({
2274
2458
  onError,
2275
2459
  onChange,
2276
2460
  onRequest,
2277
- onResponse
2461
+ onResponse,
2462
+ resolveClientUrl
2278
2463
  ]);
2279
2464
  if (remoteComponent instanceof Error) {
2280
2465
  throw remoteComponent;
@@ -2283,10 +2468,10 @@ function RemoteComponent({
2283
2468
  name: data?.name || name,
2284
2469
  bundle: data?.bundle || "default",
2285
2470
  route: data?.route || DEFAULT_ROUTE,
2286
- runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2471
+ runtime: hostStateRef.current.prevIsRemoteComponent ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2287
2472
  }) });
2288
2473
  const resetStyle = reset ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { "data-remote-components-reset": "react", children: `:host { all: initial; }` }) : null;
2289
- const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react3.createElement)(
2474
+ const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react4.createElement)(
2290
2475
  "link",
2291
2476
  {
2292
2477
  ...link,
@@ -2302,10 +2487,11 @@ function RemoteComponent({
2302
2487
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
2303
2488
  shadowRoot.innerHTML = componentHydrationHtml.current;
2304
2489
  componentHydrationHtml.current = null;
2305
- if (prevIsRemoteComponentRef.current) {
2490
+ if (hostStateRef.current.prevIsRemoteComponent) {
2306
2491
  loadStaticRemoteComponent(
2307
2492
  Array.from(shadowRoot.querySelectorAll("script")),
2308
- url
2493
+ url,
2494
+ resolveClientUrl
2309
2495
  ).then(({ mount }) => {
2310
2496
  return Promise.all(
2311
2497
  Array.from(mount).map((mountFn) => mountFn(shadowRoot))
@@ -2389,6 +2575,8 @@ function RemoteComponent({
2389
2575
  }
2390
2576
  // Annotate the CommonJS export names for ESM import in node:
2391
2577
  0 && (module.exports = {
2392
- RemoteComponent
2578
+ RemoteComponent,
2579
+ RemoteComponentsProvider,
2580
+ proxyClientRequestsThroughHost
2393
2581
  });
2394
2582
  //# sourceMappingURL=index.cjs.map