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
@@ -31,13 +31,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/next/host/client/index.tsx
32
32
  var client_exports = {};
33
33
  __export(client_exports, {
34
- RemoteComponent: () => RemoteComponent2
34
+ RemoteComponent: () => RemoteComponent2,
35
+ RemoteComponentsProvider: () => import_context3.RemoteComponentsProvider
35
36
  });
36
37
  module.exports = __toCommonJS(client_exports);
37
38
  var Image = __toESM(require("next/image"), 1);
38
39
 
39
40
  // src/react/index.tsx
40
- var import_react2 = require("react");
41
+ var import_react3 = require("react");
41
42
  var import_react_dom = require("react-dom");
42
43
 
43
44
  // src/shared/client/apply-origin.ts
@@ -52,7 +53,7 @@ var tagNames = [
52
53
  "script",
53
54
  "link"
54
55
  ];
55
- function applyOriginToNodes(doc, url) {
56
+ function applyOriginToNodes(doc, url, resolveClientUrl) {
56
57
  if (url.origin !== location.origin) {
57
58
  const nodes = doc.querySelectorAll(
58
59
  tagNames.map(
@@ -61,12 +62,15 @@ function applyOriginToNodes(doc, url) {
61
62
  );
62
63
  nodes.forEach((node) => {
63
64
  if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
64
- node.src = new URL(node.getAttribute("src") ?? "/", url).href;
65
+ const absoluteSrc = new URL(node.getAttribute("src") ?? "/", url).href;
66
+ const isScript = node.tagName.toLowerCase() === "script";
67
+ node.src = isScript ? absoluteSrc : resolveClientUrl?.(absoluteSrc) ?? absoluteSrc;
65
68
  }
66
69
  if (node.hasAttribute("href") && /^[./]+\/?/.test(node.getAttribute("href") ?? "")) {
70
+ const absoluteHref = new URL(node.getAttribute("href") ?? "/", url).href;
67
71
  node.setAttribute(
68
72
  "href",
69
- new URL(node.getAttribute("href") ?? "/", url).href
73
+ resolveClientUrl?.(absoluteHref) ?? absoluteHref
70
74
  );
71
75
  }
72
76
  if (node.hasAttribute("srcset")) {
@@ -75,7 +79,8 @@ function applyOriginToNodes(doc, url) {
75
79
  if (!urlPart)
76
80
  return entry;
77
81
  const absoluteUrl = new URL(urlPart, url).href;
78
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
82
+ const resolvedUrl = resolveClientUrl?.(absoluteUrl) ?? absoluteUrl;
83
+ return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl;
79
84
  }).join(", ");
80
85
  if (srcSet) {
81
86
  node.setAttribute("srcset", srcSet);
@@ -87,7 +92,8 @@ function applyOriginToNodes(doc, url) {
87
92
  if (!urlPart)
88
93
  return entry;
89
94
  const absoluteUrl = new URL(urlPart, url).href;
90
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
95
+ const resolvedUrl = resolveClientUrl?.(absoluteUrl) ?? absoluteUrl;
96
+ return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl;
91
97
  }).join(", ");
92
98
  if (srcSet) {
93
99
  node.setAttribute("imagesrcset", srcSet);
@@ -97,6 +103,31 @@ function applyOriginToNodes(doc, url) {
97
103
  }
98
104
  }
99
105
 
106
+ // src/shared/constants.ts
107
+ var RC_PROTECTED_REMOTE_FETCH_PATHNAME = "/rc-fetch-protected-remote";
108
+ var CORS_DOCS_URL = "https://vercel.com/docs/remote-components/concepts/cors-external-urls#accessing-cross-site-protected-remote-components";
109
+
110
+ // src/shared/client/protected-rc-fallback.ts
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
+
100
131
  // src/shared/error.ts
101
132
  var RemoteComponentsError = class extends Error {
102
133
  code = "REMOTE_COMPONENTS_ERROR";
@@ -116,6 +147,185 @@ function failedToFetchRemoteComponentError(url, { status, statusText }, help = "
116
147
  { cause: new Error(`${status} ${statusText}`) }
117
148
  );
118
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
+ }
119
329
 
120
330
  // src/shared/utils/logger.ts
121
331
  var PREFIX = "remote-components";
@@ -125,9 +335,6 @@ function logDebug(location2, message) {
125
335
  console.debug(`[${PREFIX}:${location2}]: ${message}`);
126
336
  }
127
337
  }
128
- function logInfo(location2, message) {
129
- console.info(`[${PREFIX}:${location2}]: ${message}`);
130
- }
131
338
  function logWarn(location2, message) {
132
339
  console.warn(`[${PREFIX}:${location2}]: ${message}`);
133
340
  }
@@ -138,6 +345,19 @@ function logError(location2, message, cause) {
138
345
  })
139
346
  );
140
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
+ }
141
361
 
142
362
  // src/shared/client/polyfill.tsx
143
363
  var import_jsx_runtime = (
@@ -581,19 +801,11 @@ function createRSCStream(rscName, data) {
581
801
  });
582
802
  }
583
803
 
584
- // src/shared/constants.ts
585
- var RC_PROTECTED_REMOTE_FETCH_PATHNAME = "/rc-fetch-protected-remote";
586
-
587
- // src/shared/client/protected-rc-fallback.ts
588
- function generateProtectedRcFallbackSrc(url) {
589
- return `${RC_PROTECTED_REMOTE_FETCH_PATHNAME}?url=${encodeURIComponent(url)}`;
590
- }
591
-
592
804
  // src/shared/client/webpack-patterns.ts
593
805
  var NEXT_BUNDLE_PATH_RE = /\/_next\/\[.+\](?:%20| )/;
594
806
 
595
807
  // src/shared/client/script-loader.ts
596
- async function loadScripts(scripts) {
808
+ async function loadScripts(scripts, resolveClientUrl) {
597
809
  await Promise.all(
598
810
  scripts.map((script) => {
599
811
  return new Promise((resolve, reject) => {
@@ -602,117 +814,34 @@ async function loadScripts(scripts) {
602
814
  script.src.replace(NEXT_BUNDLE_PATH_RE, "/_next/"),
603
815
  location.origin
604
816
  ).href;
605
- const loadScriptWithProtectedRcFallback = (src, isFallback = false) => {
606
- const newScript = document.createElement("script");
607
- newScript.onload = () => {
608
- if (isFallback) {
609
- logInfo(
610
- "ScriptLoader",
611
- `Successfully loaded <script src="${newSrc}"> using fallback.`
612
- );
613
- }
614
- resolve();
615
- };
616
- newScript.onerror = () => {
617
- if (!isFallback) {
618
- const fallbackSrc = generateProtectedRcFallbackSrc(newSrc);
619
- logWarn(
620
- "ScriptLoader",
621
- `Failed to load <script src="${newSrc}"> for Remote Component. Trying fallback with ${RC_PROTECTED_REMOTE_FETCH_PATHNAME} (withRemoteComponentsHost)...`
622
- );
623
- loadScriptWithProtectedRcFallback(fallbackSrc, true);
624
- } else {
625
- logError(
626
- "ScriptLoader",
627
- `Failed to load fallback for <script src="${newSrc}"> for Remote Component.`
628
- );
629
- reject(
630
- new RemoteComponentsError(
631
- `Failed to load <script src="${newSrc}"> for Remote Component. Check the URL is correct.`
632
- )
633
- );
634
- }
635
- };
636
- newScript.src = src;
637
- newScript.async = true;
638
- 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
+ }
639
836
  };
640
- loadScriptWithProtectedRcFallback(newSrc);
837
+ newScript.src = resolvedSrc;
838
+ newScript.async = true;
839
+ document.head.appendChild(newScript);
641
840
  });
642
841
  })
643
842
  );
644
843
  }
645
844
 
646
- // src/shared/utils/index.ts
647
- function escapeString(str) {
648
- return str.replace(/[^a-z0-9]/g, "_");
649
- }
650
- var attrToProp = {
651
- fetchpriority: "fetchPriority",
652
- crossorigin: "crossOrigin",
653
- imagesrcset: "imageSrcSet",
654
- imagesizes: "imageSizes",
655
- srcset: "srcSet"
656
- };
657
-
658
- // src/shared/client/const.ts
659
- var DEFAULT_ROUTE = "/";
660
- var RUNTIME_WEBPACK = "webpack";
661
- var RUNTIME_TURBOPACK = "turbopack";
662
- var RUNTIME_SCRIPT = "script";
663
- var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
664
- function getBundleKey(bundle) {
665
- return escapeString(bundle);
666
- }
667
-
668
- // src/shared/utils/abort.ts
669
- function isAbortError(error) {
670
- if (error instanceof DOMException && error.name === "AbortError") {
671
- return true;
672
- }
673
- if (error !== null && typeof error === "object" && "name" in error && error.name === "AbortError" && "message" in error && typeof error.message === "string") {
674
- const e = error;
675
- return typeof e.code === "number" || e.constructor?.name === "DOMException";
676
- }
677
- return false;
678
- }
679
-
680
- // src/shared/client/fetch-with-protected-rc-fallback.ts
681
- async function fetchWithProtectedRcFallback(url, init) {
682
- try {
683
- const res = await fetch(url, init);
684
- return res;
685
- } catch (error) {
686
- if (isAbortError(error)) {
687
- throw error;
688
- }
689
- const parsedUrl = new URL(url);
690
- if (typeof document === "object" && typeof document.location === "object" && document.location.origin !== parsedUrl.origin) {
691
- logWarn(
692
- "FetchRemoteComponent",
693
- "Request failed due to CORS, attempting to fetch it via the withRemoteComponentsHost proxy."
694
- );
695
- const proxiedRes = await fetch(
696
- generateProtectedRcFallbackSrc(parsedUrl.href),
697
- init?.signal ? { signal: init.signal } : void 0
698
- );
699
- if (proxiedRes.status === 200) {
700
- logInfo(
701
- "FetchRemoteComponent",
702
- `Successfully fetched ${parsedUrl.href} with fallback withRemoteComponentsHost proxy`
703
- );
704
- return proxiedRes;
705
- } else {
706
- logError(
707
- "FetchRemoteComponent",
708
- `Could not proxy remote: [response status ${proxiedRes.status}] ${await proxiedRes.text()}`
709
- );
710
- }
711
- }
712
- throw error;
713
- }
714
- }
715
-
716
845
  // src/shared/client/turbopack-patterns.ts
717
846
  var REMOTE_SHARED_MARKER_RE = /(?:self|[a-z])\.TURBOPACK_REMOTE_SHARED/;
718
847
  var REMOTE_SHARED_ASSIGNMENT_RE = /\.TURBOPACK_REMOTE_SHARED=await (?:__turbopack_context__|e)\.A\((?<sharedModuleId>[0-9]+)\)/;
@@ -722,7 +851,7 @@ var ASYNC_MODULE_ALL_RE = /(?<ctx>__turbopack_context__|e)=>\{\k<ctx>\.v\((?<vCb
722
851
  var TURBOPACK_GLOBAL_RE = /(?:globalThis|self)\s*(?:\.TURBOPACK|\[\s*["']TURBOPACK["']\s*\])/;
723
852
 
724
853
  // src/shared/client/chunk-loader.ts
725
- function createChunkLoader(runtime) {
854
+ function createChunkLoader(runtime, resolveClientUrl) {
726
855
  return function __turbopack_chunk_load__(chunkId, scriptBundle) {
727
856
  logDebug("ChunkLoader", `Loading chunk: "${chunkId}"`);
728
857
  const self = globalThis;
@@ -762,9 +891,10 @@ function createChunkLoader(runtime) {
762
891
  logDebug("ChunkLoader", `Returning cached promise for: "${url}"`);
763
892
  return self.__remote_components_turbopack_chunk_loader_promise__[url];
764
893
  }
765
- logDebug("ChunkLoader", `Fetching chunk from: "${url}"`);
894
+ const resolvedUrl = resolveClientUrl?.(url) ?? url;
895
+ logDebug("ChunkLoader", `Fetching chunk from: "${resolvedUrl}"`);
766
896
  self.__remote_components_turbopack_chunk_loader_promise__[url] = new Promise((resolve, reject) => {
767
- fetchWithProtectedRcFallback(url).then((res) => res.text()).then((code) => {
897
+ fetch(resolvedUrl).then((res) => res.text()).then((code) => {
768
898
  const hasTurbopack = TURBOPACK_GLOBAL_RE.test(code);
769
899
  if (hasTurbopack) {
770
900
  return handleTurbopackChunk(code, bundle ?? "", url);
@@ -777,7 +907,19 @@ function createChunkLoader(runtime) {
777
907
  "ChunkLoader",
778
908
  `First 500 chars of chunk: ${code.slice(0, 500)}`
779
909
  );
780
- }).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
+ });
781
923
  });
782
924
  return self.__remote_components_turbopack_chunk_loader_promise__[url];
783
925
  };
@@ -1270,7 +1412,7 @@ function getSharedModule(bundle, id) {
1270
1412
  }
1271
1413
 
1272
1414
  // src/shared/client/webpack-adapter.ts
1273
- 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) {
1274
1416
  const self = globalThis;
1275
1417
  if (!self.__remote_bundle_url__) {
1276
1418
  self.__remote_bundle_url__ = {};
@@ -1282,7 +1424,7 @@ async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location
1282
1424
  self.__original_webpack_chunk_load__ = self.__webpack_chunk_load__;
1283
1425
  self.__original_webpack_require__ = self.__webpack_require__;
1284
1426
  }
1285
- self.__webpack_chunk_load__ = createChunkLoader(runtime);
1427
+ self.__webpack_chunk_load__ = createChunkLoader(runtime, resolveClientUrl);
1286
1428
  self.__webpack_require__ = createModuleRequire(runtime);
1287
1429
  self.__webpack_require_type__ = runtime;
1288
1430
  if (self.__remote_webpack_require__ && runtime === RUNTIME_TURBOPACK) {
@@ -1377,7 +1519,8 @@ async function loadRemoteComponent({
1377
1519
  scripts = [],
1378
1520
  shared = Promise.resolve({}),
1379
1521
  remoteShared = {},
1380
- container
1522
+ container,
1523
+ resolveClientUrl
1381
1524
  }) {
1382
1525
  try {
1383
1526
  if (runtime === "webpack") {
@@ -1386,7 +1529,7 @@ async function loadRemoteComponent({
1386
1529
  self.__DISABLE_WEBPACK_EXEC__ = {};
1387
1530
  }
1388
1531
  self.__DISABLE_WEBPACK_EXEC__[bundle] = true;
1389
- await loadScripts(scripts);
1532
+ await loadScripts(scripts, resolveClientUrl);
1390
1533
  }
1391
1534
  const hostShared = await shared;
1392
1535
  logDebug(
@@ -1407,7 +1550,8 @@ async function loadRemoteComponent({
1407
1550
  url,
1408
1551
  bundle,
1409
1552
  hostShared,
1410
- remoteShared
1553
+ remoteShared,
1554
+ resolveClientUrl
1411
1555
  );
1412
1556
  if (bundle) {
1413
1557
  const resolve = {
@@ -1496,6 +1640,25 @@ function loadNextPagesComponent(bundle, route, nextData, name, container) {
1496
1640
  return { component };
1497
1641
  }
1498
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
+
1499
1662
  // src/shared/client/set-attributes-from-props.ts
1500
1663
  var DOMAttributeNames = {
1501
1664
  acceptCharset: "accept-charset",
@@ -1539,27 +1702,21 @@ function setAttributesFromProps(el, props) {
1539
1702
  }
1540
1703
 
1541
1704
  // src/shared/client/static-loader.ts
1542
- async function importViaProxy(absoluteSrc) {
1543
- const proxyUrl = new URL(
1544
- generateProtectedRcFallbackSrc(absoluteSrc),
1545
- location.href
1546
- ).href;
1547
- const response = await fetch(proxyUrl);
1705
+ async function importViaCallback(absoluteSrc, resolveClientUrl) {
1706
+ const resolvedUrl = resolveClientUrl(absoluteSrc) ?? absoluteSrc;
1707
+ const fetchUrl = new URL(resolvedUrl, location.href).href;
1708
+ const response = await fetch(fetchUrl);
1548
1709
  if (!response.ok)
1549
- throw new Error(`Proxy fetch failed: ${response.status}`);
1550
- logInfo(
1551
- "StaticLoader",
1552
- `Successfully loaded ${absoluteSrc} via protected RC proxy fallback.`
1553
- );
1710
+ throw new Error(`Proxied fetch failed: ${response.status}`);
1554
1711
  const content = (await response.text()).replace(/import\.meta\.url/g, JSON.stringify(absoluteSrc)).replace(
1555
1712
  /\b(from|import)\s*(["'])(\.\.?\/[^"']+)\2/g,
1556
1713
  (_, keyword, quote, relativePath) => {
1557
1714
  const absoluteImportUrl = new URL(relativePath, absoluteSrc).href;
1558
- const absoluteProxyUrl = new URL(
1559
- generateProtectedRcFallbackSrc(absoluteImportUrl),
1715
+ const resolvedImportUrl = new URL(
1716
+ resolveClientUrl(absoluteImportUrl) ?? absoluteImportUrl,
1560
1717
  location.href
1561
1718
  ).href;
1562
- return `${keyword} ${quote}${absoluteProxyUrl}${quote}`;
1719
+ return `${keyword} ${quote}${resolvedImportUrl}${quote}`;
1563
1720
  }
1564
1721
  );
1565
1722
  const moduleBlobUrl = URL.createObjectURL(
@@ -1593,6 +1750,20 @@ async function importViaProxy(absoluteSrc) {
1593
1750
  delete registry[absoluteSrc];
1594
1751
  return mod;
1595
1752
  }
1753
+ async function importDirectly(absoluteSrc) {
1754
+ try {
1755
+ return await import(
1756
+ /* @vite-ignore */
1757
+ /* webpackIgnore: true */
1758
+ absoluteSrc
1759
+ );
1760
+ } catch (importError) {
1761
+ if (!absoluteSrc.startsWith("blob:")) {
1762
+ warnCrossOriginFetchError("StaticLoader", absoluteSrc);
1763
+ }
1764
+ throw importError;
1765
+ }
1766
+ }
1596
1767
  function resolveScriptSrc(script, url) {
1597
1768
  const rawSrc = typeof script.getAttribute === "function" ? script.getAttribute("src") ?? script.src : script.src;
1598
1769
  if (!rawSrc && script.textContent) {
@@ -1605,24 +1776,7 @@ function resolveScriptSrc(script, url) {
1605
1776
  }
1606
1777
  return rawSrc;
1607
1778
  }
1608
- async function importScriptMod(absoluteSrc) {
1609
- try {
1610
- return await import(
1611
- /* @vite-ignore */
1612
- /* webpackIgnore: true */
1613
- absoluteSrc
1614
- );
1615
- } catch (importError) {
1616
- if (absoluteSrc.startsWith("blob:"))
1617
- throw importError;
1618
- logWarn(
1619
- "StaticLoader",
1620
- `Direct import of ${absoluteSrc} failed, attempting via protected RC proxy fallback.`
1621
- );
1622
- return importViaProxy(absoluteSrc);
1623
- }
1624
- }
1625
- async function loadStaticRemoteComponent(scripts, url) {
1779
+ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
1626
1780
  const self = globalThis;
1627
1781
  if (self.__remote_script_entrypoint_mount__?.[url.href]) {
1628
1782
  self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
@@ -1635,7 +1789,7 @@ async function loadStaticRemoteComponent(scripts, url) {
1635
1789
  try {
1636
1790
  const src = resolveScriptSrc(script, url);
1637
1791
  const absoluteSrc = new URL(src, url).href;
1638
- const mod = await importScriptMod(absoluteSrc);
1792
+ const mod = resolveClientUrl ? await importViaCallback(absoluteSrc, resolveClientUrl) : await importDirectly(absoluteSrc);
1639
1793
  if (src.startsWith("blob:")) {
1640
1794
  URL.revokeObjectURL(src);
1641
1795
  }
@@ -1697,6 +1851,32 @@ async function loadStaticRemoteComponent(scripts, url) {
1697
1851
  );
1698
1852
  }
1699
1853
 
1854
+ // src/shared/contract/host-state.ts
1855
+ function createHostState() {
1856
+ return {
1857
+ stage: "idle",
1858
+ prevSrc: void 0,
1859
+ prevUrl: void 0,
1860
+ prevName: void 0,
1861
+ prevIsRemoteComponent: false,
1862
+ abortController: void 0
1863
+ };
1864
+ }
1865
+
1866
+ // src/shared/contract/resolve-name-from-src.ts
1867
+ function resolveNameFromSrc(src, defaultName) {
1868
+ if (!src) {
1869
+ return defaultName;
1870
+ }
1871
+ const hash = typeof src === "string" ? src : src.hash;
1872
+ const hashIndex = hash.indexOf("#");
1873
+ if (hashIndex < 0) {
1874
+ return defaultName;
1875
+ }
1876
+ const name = hash.slice(hashIndex + 1);
1877
+ return name || defaultName;
1878
+ }
1879
+
1700
1880
  // src/shared/ssr/fetch-headers.ts
1701
1881
  function remoteFetchHeaders() {
1702
1882
  return {
@@ -1733,7 +1913,12 @@ async function fetchWithHooks(url, additionalInit, options = {}) {
1733
1913
  };
1734
1914
  let res = await onRequest?.(url, init, hookOptions);
1735
1915
  if (!res) {
1736
- res = await fetchWithProtectedRcFallback(url, init);
1916
+ try {
1917
+ res = await fetch(url, init);
1918
+ } catch (error) {
1919
+ warnCrossOriginFetchError("FetchRemoteComponent", url);
1920
+ throw error;
1921
+ }
1737
1922
  }
1738
1923
  const transformedRes = await onResponse?.(url, res, hookOptions);
1739
1924
  if (transformedRes) {
@@ -1751,15 +1936,34 @@ function getClientOrServerUrl(src, serverFallback) {
1751
1936
  return typeof src === "string" ? new URL(src, fallback) : src;
1752
1937
  }
1753
1938
 
1754
- // src/react/hooks/use-shadow-root.ts
1939
+ // src/react/hooks/use-resolve-client-url.ts
1755
1940
  var import_react = require("react");
1941
+ var import_context = require("#internal/react/context");
1942
+
1943
+ // src/shared/client/default-resolve-client-url.ts
1944
+ function bindResolveClientUrl(prop, remoteSrc) {
1945
+ return prop ? withRemoteSrc(prop, remoteSrc) : void 0;
1946
+ }
1947
+
1948
+ // src/react/hooks/use-resolve-client-url.ts
1949
+ function useResolveClientUrl(prop, urlHref) {
1950
+ const { resolveClientUrl: contextValue } = (0, import_context.useRemoteComponentsContext)();
1951
+ const resolveClientUrl = prop ?? contextValue;
1952
+ return (0, import_react.useMemo)(
1953
+ () => bindResolveClientUrl(resolveClientUrl, urlHref),
1954
+ [resolveClientUrl, urlHref]
1955
+ );
1956
+ }
1957
+
1958
+ // src/react/hooks/use-shadow-root.ts
1959
+ var import_react2 = require("react");
1756
1960
  function useShadowRoot({
1757
1961
  isolate,
1758
1962
  mode,
1759
1963
  keySuffix
1760
1964
  }) {
1761
- const shadowRootContainerRef = (0, import_react.useRef)(null);
1762
- const [shadowRoot, setShadowRoot] = (0, import_react.useState)(() => {
1965
+ const shadowRootContainerRef = (0, import_react2.useRef)(null);
1966
+ const [shadowRoot, setShadowRoot] = (0, import_react2.useState)(() => {
1763
1967
  const self = globalThis;
1764
1968
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1765
1969
  const ssrShadowRoot = typeof document !== "undefined" ? document.querySelector(
@@ -1768,7 +1972,7 @@ function useShadowRoot({
1768
1972
  self[shadowRootKey] = null;
1769
1973
  return ssrShadowRoot;
1770
1974
  });
1771
- (0, import_react.useLayoutEffect)(() => {
1975
+ (0, import_react2.useLayoutEffect)(() => {
1772
1976
  if (isolate !== false && typeof document !== "undefined" && (!shadowRoot || !shadowRoot.isConnected)) {
1773
1977
  const self = globalThis;
1774
1978
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
@@ -1800,7 +2004,7 @@ function useShadowRoot({
1800
2004
  return { shadowRoot, shadowRootContainerRef };
1801
2005
  }
1802
2006
 
1803
- // src/react/utils/parse-remote-html.ts
2007
+ // src/react/utils/extract-remote-html.ts
1804
2008
  var DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
1805
2009
  function getRemoteComponentHtml(html) {
1806
2010
  if (typeof document === "undefined")
@@ -1823,11 +2027,12 @@ function getRemoteComponentHtml(html) {
1823
2027
  }
1824
2028
 
1825
2029
  // src/react/index.tsx
2030
+ var import_context2 = require("#internal/react/context");
1826
2031
  var import_jsx_runtime2 = (
1827
2032
  // TODO: remove wrapper div by converting HTML to RSC or React tree
1828
2033
  require("react/jsx-runtime")
1829
2034
  );
1830
- var import_react3 = require("react");
2035
+ var import_react4 = require("react");
1831
2036
  function RemoteComponent({
1832
2037
  src,
1833
2038
  isolate,
@@ -1842,40 +2047,34 @@ function RemoteComponent({
1842
2047
  onError,
1843
2048
  onChange,
1844
2049
  onRequest,
1845
- onResponse
2050
+ onResponse,
2051
+ resolveClientUrl: _resolveClientUrl
1846
2052
  }) {
1847
- const instanceId = (0, import_react2.useId)();
1848
- const name = (0, import_react2.useMemo)(() => {
1849
- if (typeof src === "string") {
1850
- const url2 = new URL(
1851
- src,
1852
- typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
1853
- );
1854
- if (url2.hash) {
1855
- return url2.hash.slice(1);
1856
- }
1857
- } else if (typeof src === "object" && "hash" in src && src.hash) {
1858
- return src.hash.slice(1) || nameProp;
1859
- }
1860
- return nameProp;
1861
- }, [src, nameProp]);
1862
- const [data, setData] = (0, import_react2.useState)(null);
1863
- const url = (0, import_react2.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
2053
+ const instanceId = (0, import_react3.useId)();
2054
+ const name = (0, import_react3.useMemo)(
2055
+ () => resolveNameFromSrc(src, nameProp),
2056
+ [src, nameProp]
2057
+ );
2058
+ const [data, setData] = (0, import_react3.useState)(null);
2059
+ const url = (0, import_react3.useMemo)(() => getClientOrServerUrl(src, DUMMY_FALLBACK), [src]);
2060
+ const resolveClientUrl = useResolveClientUrl(_resolveClientUrl, url.href);
1864
2061
  const id = url.origin === (typeof location !== "undefined" ? location.origin : DUMMY_FALLBACK) ? url.pathname : url.href;
1865
- const keySuffix = `${escapeString(id)}_${escapeString(data?.name ?? name)}_${escapeString(instanceId)}`;
1866
- const [remoteComponent, setRemoteComponent] = (0, import_react2.useState)(null);
2062
+ const keySuffix = `${escapeString(id)}_${escapeString(
2063
+ data?.name ?? name
2064
+ )}_${escapeString(instanceId)}`;
2065
+ const [remoteComponent, setRemoteComponent] = (0, import_react3.useState)(null);
1867
2066
  const { shadowRoot, shadowRootContainerRef } = useShadowRoot({
1868
2067
  isolate,
1869
2068
  mode,
1870
2069
  keySuffix
1871
2070
  });
1872
- const htmlRef = (0, import_react2.useRef)(
2071
+ const htmlRef = (0, import_react3.useRef)(
1873
2072
  typeof document !== "undefined" ? document.querySelector(
1874
2073
  `[data-remote-component-id="shadowroot_${keySuffix}"]`
1875
2074
  )?.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
1876
2075
  );
1877
- const endTemplateRef = (0, import_react2.useRef)(null);
1878
- const childrenRef = (0, import_react2.useRef)(
2076
+ const endTemplateRef = (0, import_react3.useRef)(null);
2077
+ const childrenRef = (0, import_react3.useRef)(
1879
2078
  typeof document !== "undefined" ? (() => {
1880
2079
  let el = document.querySelector(`template[id="${name}_start"]`);
1881
2080
  const elements = [];
@@ -1888,20 +2087,17 @@ function RemoteComponent({
1888
2087
  return elements;
1889
2088
  })() : []
1890
2089
  );
1891
- const prevSrcRef = (0, import_react2.useRef)(null);
1892
- const componentHydrationHtml = (0, import_react2.useRef)(null);
1893
- const prevIsRemoteComponentRef = (0, import_react2.useRef)(false);
1894
- const prevUrlRef = (0, import_react2.useRef)(null);
1895
- const prevRemoteComponentContainerRef = (0, import_react2.useRef)(null);
1896
- const unmountRef = (0, import_react2.useRef)(null);
1897
- const prevNameRef = (0, import_react2.useRef)(void 0);
1898
- (0, import_react2.useLayoutEffect)(() => {
2090
+ const hostStateRef = (0, import_react3.useRef)(createHostState());
2091
+ const componentHydrationHtml = (0, import_react3.useRef)(null);
2092
+ const prevRemoteComponentContainerRef = (0, import_react3.useRef)(null);
2093
+ const unmountRef = (0, import_react3.useRef)(null);
2094
+ (0, import_react3.useLayoutEffect)(() => {
1899
2095
  const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
1900
2096
  return () => {
1901
2097
  delete globalThis[shadowRootKey];
1902
2098
  };
1903
2099
  }, [keySuffix]);
1904
- (0, import_react2.useLayoutEffect)(() => {
2100
+ (0, import_react3.useLayoutEffect)(() => {
1905
2101
  if (childrenRef.current.length > 0 && remoteComponent) {
1906
2102
  childrenRef.current.forEach((el) => {
1907
2103
  el.remove();
@@ -1909,7 +2105,7 @@ function RemoteComponent({
1909
2105
  childrenRef.current = [];
1910
2106
  }
1911
2107
  }, [remoteComponent]);
1912
- (0, import_react2.useLayoutEffect)(() => {
2108
+ (0, import_react3.useLayoutEffect)(() => {
1913
2109
  if (shadowRoot && remoteComponent) {
1914
2110
  const resetStyles = shadowRoot.querySelectorAll(
1915
2111
  "style[data-remote-components-reset]"
@@ -1932,16 +2128,20 @@ function RemoteComponent({
1932
2128
  }
1933
2129
  }
1934
2130
  }, [shadowRoot, remoteComponent, name]);
1935
- (0, import_react2.useEffect)(() => {
1936
- if (src && src !== prevSrcRef.current) {
1937
- const previousSrc = prevSrcRef.current;
1938
- const previousName = prevNameRef.current;
1939
- prevSrcRef.current = src;
2131
+ (0, import_react3.useEffect)(() => {
2132
+ if (src && src !== hostStateRef.current.prevSrc) {
2133
+ const previousSrc = hostStateRef.current.prevSrc;
2134
+ const previousName = hostStateRef.current.prevName;
2135
+ hostStateRef.current.prevSrc = src;
1940
2136
  if (previousSrc !== null) {
1941
2137
  htmlRef.current = null;
1942
2138
  }
2139
+ hostStateRef.current.abortController?.abort();
2140
+ hostStateRef.current.abortController = new AbortController();
2141
+ const { signal } = hostStateRef.current.abortController;
1943
2142
  onBeforeLoad?.(src);
1944
- (0, import_react2.startTransition)(async () => {
2143
+ hostStateRef.current.stage = "loading";
2144
+ (0, import_react3.startTransition)(async () => {
1945
2145
  try {
1946
2146
  let html = getRemoteComponentHtml(
1947
2147
  htmlRef.current ?? (endTemplateRef.current?.previousElementSibling?.tagName === "div" ? endTemplateRef.current.previousElementSibling.innerHTML : "")
@@ -1950,86 +2150,45 @@ function RemoteComponent({
1950
2150
  const fetchInit = {
1951
2151
  credentials
1952
2152
  };
1953
- const abortController = new AbortController();
1954
- const res = await fetchWithHooks(url, fetchInit, {
2153
+ const resolvedUrl = new URL(
2154
+ resolveClientUrl?.(url.href) ?? url.href,
2155
+ location.href
2156
+ );
2157
+ const res = await fetchWithHooks(resolvedUrl, fetchInit, {
1955
2158
  onRequest,
1956
2159
  onResponse,
1957
- abortController
2160
+ abortController: hostStateRef.current.abortController
1958
2161
  });
1959
2162
  if (!res || !res.ok) {
1960
- let error = failedToFetchRemoteComponentError(
1961
- url.href,
1962
- res ?? new Response(null, { status: 0 })
1963
- );
1964
- try {
1965
- const body = await res.text();
1966
- const parser2 = new DOMParser();
1967
- const doc2 = parser2.parseFromString(body, "text/html");
1968
- const errorTemplate = doc2.querySelector(
1969
- "template[data-next-error-message]"
1970
- );
1971
- const errorMessage = errorTemplate?.getAttribute(
1972
- "data-next-error-message"
1973
- );
1974
- const errorStack = errorTemplate?.getAttribute(
1975
- "data-next-error-stack"
1976
- );
1977
- if (errorMessage) {
1978
- error = new RemoteComponentsError(errorMessage);
1979
- if (errorStack) {
1980
- error.stack = errorStack;
1981
- }
1982
- }
1983
- } catch (parseError) {
1984
- if (isAbortError(parseError))
1985
- throw parseError;
1986
- }
1987
- throw error;
2163
+ throw await errorFromFailedFetch(url.href, resolvedUrl, res);
1988
2164
  }
1989
2165
  const remoteHtml = await res.text();
2166
+ if (signal.aborted)
2167
+ return;
1990
2168
  htmlRef.current = remoteHtml;
1991
2169
  html = getRemoteComponentHtml(remoteHtml);
1992
2170
  }
2171
+ if (signal.aborted)
2172
+ return;
1993
2173
  const parser = new DOMParser();
1994
2174
  const doc = parser.parseFromString(html, "text/html");
1995
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
1996
- `div[data-bundle][data-route][id^="${name}"]`
1997
- ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
1998
- throw multipleRemoteComponentsError(url.href);
1999
- }
2000
- 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
2001
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
2002
- doc.querySelector("div#__next") ?? // fallback to the remote-component web component
2003
- doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
2004
- const nextData = JSON.parse(
2005
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
2006
- );
2007
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
2008
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
2009
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
2010
- const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
2011
- const metadata = {
2175
+ const {
2176
+ component,
2012
2177
  name: remoteName,
2013
- bundle,
2014
- route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
2015
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
2016
- };
2017
- const remoteSharedEl = doc.querySelector(
2018
- `#${remoteName}_shared[data-remote-components-shared]`
2019
- );
2020
- const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
2021
- remoteSharedEl?.remove();
2022
- if (!component || !(rsc || nextData || isRemoteComponent)) {
2023
- throw new RemoteComponentsError(
2024
- `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>?`
2025
- );
2026
- }
2027
- if (prevIsRemoteComponentRef.current) {
2178
+ isRemoteComponent,
2179
+ metadata,
2180
+ nextData,
2181
+ rsc,
2182
+ remoteShared,
2183
+ links: linkElements,
2184
+ scripts: scriptElements
2185
+ } = parseRemoteComponentDocument(doc, name, url);
2186
+ if (hostStateRef.current.prevIsRemoteComponent) {
2028
2187
  if (shadowRoot) {
2029
2188
  shadowRoot.innerHTML = "";
2030
2189
  }
2031
2190
  const self = globalThis;
2032
- const prevUrl = prevUrlRef.current;
2191
+ const prevUrl = hostStateRef.current.prevUrl;
2033
2192
  if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
2034
2193
  const unmountPromises = Promise.all(
2035
2194
  Array.from(unmountRef.current ?? []).map(
@@ -2042,15 +2201,11 @@ function RemoteComponent({
2042
2201
  await unmountPromises;
2043
2202
  }
2044
2203
  }
2045
- prevIsRemoteComponentRef.current = isRemoteComponent;
2046
- prevUrlRef.current = url;
2047
- prevNameRef.current = remoteName;
2048
- applyOriginToNodes(doc, url);
2049
- const links = Array.from(
2050
- doc.querySelectorAll("link[href]")
2051
- ).filter((link) => {
2052
- return !component.contains(link);
2053
- }).map((link) => ({
2204
+ hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2205
+ hostStateRef.current.prevUrl = url;
2206
+ hostStateRef.current.prevName = remoteName;
2207
+ applyOriginToNodes(doc, url, resolveClientUrl);
2208
+ const links = linkElements.map((link) => ({
2054
2209
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2055
2210
  ...link.getAttributeNames().reduce((acc, key) => {
2056
2211
  if (key !== "href") {
@@ -2059,7 +2214,7 @@ function RemoteComponent({
2059
2214
  return acc;
2060
2215
  }, {})
2061
2216
  }));
2062
- const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
2217
+ const scripts = scriptElements;
2063
2218
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2064
2219
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2065
2220
  );
@@ -2150,7 +2305,7 @@ function RemoteComponent({
2150
2305
  );
2151
2306
  }
2152
2307
  if (isRemoteComponent) {
2153
- if (previousSrc !== null) {
2308
+ if (previousSrc !== void 0) {
2154
2309
  onChange?.({
2155
2310
  previousSrc,
2156
2311
  nextSrc: src,
@@ -2169,7 +2324,8 @@ function RemoteComponent({
2169
2324
  setRemoteComponent(null);
2170
2325
  const { mount, unmount } = await loadStaticRemoteComponent(
2171
2326
  Array.from(shadowRoot.querySelectorAll("script")),
2172
- url
2327
+ url,
2328
+ resolveClientUrl
2173
2329
  );
2174
2330
  unmountRef.current = unmount;
2175
2331
  await Promise.all(
@@ -2189,7 +2345,8 @@ function RemoteComponent({
2189
2345
  htmlRef.current = null;
2190
2346
  const { mount, unmount } = await loadStaticRemoteComponent(
2191
2347
  Array.from(component.querySelectorAll("script")),
2192
- url
2348
+ url,
2349
+ resolveClientUrl
2193
2350
  );
2194
2351
  unmountRef.current = unmount;
2195
2352
  await Promise.all(
@@ -2199,12 +2356,13 @@ function RemoteComponent({
2199
2356
  );
2200
2357
  onLoad?.(src);
2201
2358
  }
2359
+ hostStateRef.current.stage = "loaded";
2202
2360
  } else {
2203
2361
  const result = await loadRemoteComponent({
2204
2362
  url,
2205
2363
  name: remoteName,
2206
2364
  rscName,
2207
- bundle,
2365
+ bundle: metadata.bundle,
2208
2366
  route: metadata.route,
2209
2367
  runtime: metadata.runtime,
2210
2368
  data: newData.data,
@@ -2232,13 +2390,14 @@ function RemoteComponent({
2232
2390
  ...userShared
2233
2391
  },
2234
2392
  remoteShared,
2235
- container: shadowRoot
2393
+ container: shadowRoot,
2394
+ resolveClientUrl
2236
2395
  });
2237
2396
  if (rsc) {
2238
2397
  rsc.remove();
2239
2398
  }
2240
2399
  setData(newData);
2241
- if (previousSrc !== null) {
2400
+ if (previousSrc !== void 0) {
2242
2401
  onChange?.({
2243
2402
  previousSrc,
2244
2403
  nextSrc: src,
@@ -2247,17 +2406,21 @@ function RemoteComponent({
2247
2406
  });
2248
2407
  }
2249
2408
  if (result.error) {
2409
+ hostStateRef.current.stage = "error";
2250
2410
  setRemoteComponent(result.error);
2251
2411
  onError?.(result.error);
2252
2412
  } else {
2413
+ hostStateRef.current.stage = "loaded";
2253
2414
  setRemoteComponent(result.component);
2254
2415
  onLoad?.(src);
2255
2416
  }
2256
2417
  }
2257
2418
  } catch (error) {
2258
2419
  if (isAbortError(error)) {
2420
+ hostStateRef.current.stage = "idle";
2259
2421
  return;
2260
2422
  }
2423
+ hostStateRef.current.stage = "error";
2261
2424
  setRemoteComponent(error);
2262
2425
  onError?.(error);
2263
2426
  }
@@ -2278,7 +2441,8 @@ function RemoteComponent({
2278
2441
  onError,
2279
2442
  onChange,
2280
2443
  onRequest,
2281
- onResponse
2444
+ onResponse,
2445
+ resolveClientUrl
2282
2446
  ]);
2283
2447
  if (remoteComponent instanceof Error) {
2284
2448
  throw remoteComponent;
@@ -2287,10 +2451,10 @@ function RemoteComponent({
2287
2451
  name: data?.name || name,
2288
2452
  bundle: data?.bundle || "default",
2289
2453
  route: data?.route || DEFAULT_ROUTE,
2290
- runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2454
+ runtime: hostStateRef.current.prevIsRemoteComponent ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
2291
2455
  }) });
2292
2456
  const resetStyle = reset ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { "data-remote-components-reset": "react", children: `:host { all: initial; }` }) : null;
2293
- const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react3.createElement)(
2457
+ const linksToRender = data?.links?.map((link) => /* @__PURE__ */ (0, import_react4.createElement)(
2294
2458
  "link",
2295
2459
  {
2296
2460
  ...link,
@@ -2306,10 +2470,11 @@ function RemoteComponent({
2306
2470
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
2307
2471
  shadowRoot.innerHTML = componentHydrationHtml.current;
2308
2472
  componentHydrationHtml.current = null;
2309
- if (prevIsRemoteComponentRef.current) {
2473
+ if (hostStateRef.current.prevIsRemoteComponent) {
2310
2474
  loadStaticRemoteComponent(
2311
2475
  Array.from(shadowRoot.querySelectorAll("script")),
2312
- url
2476
+ url,
2477
+ resolveClientUrl
2313
2478
  ).then(({ mount }) => {
2314
2479
  return Promise.all(
2315
2480
  Array.from(mount).map((mountFn) => mountFn(shadowRoot))
@@ -2392,6 +2557,9 @@ function RemoteComponent({
2392
2557
  ] });
2393
2558
  }
2394
2559
 
2560
+ // src/next/host/client/index.tsx
2561
+ var import_context3 = require("#internal/react/context");
2562
+
2395
2563
  // src/next/host/app-router-compat.tsx
2396
2564
  var import_navigation = require("next/navigation");
2397
2565
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -2502,6 +2670,7 @@ function RemoteComponent2(props) {
2502
2670
  }
2503
2671
  // Annotate the CommonJS export names for ESM import in node:
2504
2672
  0 && (module.exports = {
2505
- RemoteComponent
2673
+ RemoteComponent,
2674
+ RemoteComponentsProvider
2506
2675
  });
2507
2676
  //# sourceMappingURL=index.cjs.map