remote-components 0.1.0 → 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 (62) hide show
  1. package/dist/{component-loader-76eb1b8b.d.ts → component-loader-21865da3.d.ts} +140 -16
  2. package/dist/host-config-58cdccea.d.ts +87 -0
  3. package/dist/html/host.cjs +294 -162
  4. package/dist/html/host.cjs.map +1 -1
  5. package/dist/html/host.js +294 -162
  6. package/dist/html/host.js.map +1 -1
  7. package/dist/internal/next/host/app-router-client.cjs +9 -7
  8. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  9. package/dist/internal/next/host/app-router-client.d.ts +32 -19
  10. package/dist/internal/next/host/app-router-client.js +9 -7
  11. package/dist/internal/next/host/app-router-client.js.map +1 -1
  12. package/dist/internal/next/remote/render-server.cjs.map +1 -1
  13. package/dist/internal/next/remote/render-server.d.ts +13 -14
  14. package/dist/internal/next/remote/render-server.js.map +1 -1
  15. package/dist/internal/shared/client/proxy-through-host.cjs +15 -1
  16. package/dist/internal/shared/client/proxy-through-host.cjs.map +1 -1
  17. package/dist/internal/shared/client/proxy-through-host.d.ts +5 -0
  18. package/dist/internal/shared/client/proxy-through-host.js +15 -1
  19. package/dist/internal/shared/client/proxy-through-host.js.map +1 -1
  20. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  21. package/dist/internal/shared/client/remote-component.d.ts +2 -2
  22. package/dist/internal/shared/client/remote-component.js.map +1 -1
  23. package/dist/internal/shared/contract/host-state.cjs +38 -0
  24. package/dist/internal/shared/contract/host-state.cjs.map +1 -0
  25. package/dist/internal/shared/contract/host-state.d.ts +53 -0
  26. package/dist/internal/shared/contract/host-state.js +14 -0
  27. package/dist/internal/shared/contract/host-state.js.map +1 -0
  28. package/dist/internal/shared/contract/resolve-name-from-src.cjs +40 -0
  29. package/dist/internal/shared/contract/resolve-name-from-src.cjs.map +1 -0
  30. package/dist/internal/shared/contract/resolve-name-from-src.d.ts +13 -0
  31. package/dist/internal/shared/contract/resolve-name-from-src.js +16 -0
  32. package/dist/internal/shared/contract/resolve-name-from-src.js.map +1 -0
  33. package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
  34. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  35. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +1 -1
  36. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  37. package/dist/internal/shared/ssr/fetch-with-hooks.d.ts +1 -1
  38. package/dist/next/host/app-router-server.cjs.map +1 -1
  39. package/dist/next/host/app-router-server.d.ts +11 -41
  40. package/dist/next/host/app-router-server.js.map +1 -1
  41. package/dist/next/host/client/index.cjs +203 -95
  42. package/dist/next/host/client/index.cjs.map +1 -1
  43. package/dist/next/host/client/index.d.ts +1 -1
  44. package/dist/next/host/client/index.js +203 -95
  45. package/dist/next/host/client/index.js.map +1 -1
  46. package/dist/next/host/pages-router-client.cjs.map +1 -1
  47. package/dist/next/host/pages-router-client.d.ts +13 -36
  48. package/dist/next/host/pages-router-client.js.map +1 -1
  49. package/dist/next/host/pages-router-server.cjs.map +1 -1
  50. package/dist/next/host/pages-router-server.d.ts +17 -42
  51. package/dist/next/host/pages-router-server.js.map +1 -1
  52. package/dist/next/index.cjs.map +1 -1
  53. package/dist/next/index.d.ts +13 -39
  54. package/dist/next/index.js.map +1 -1
  55. package/dist/next/remote/server.d.ts +4 -0
  56. package/dist/react/index.cjs +203 -95
  57. package/dist/react/index.cjs.map +1 -1
  58. package/dist/react/index.d.ts +12 -49
  59. package/dist/react/index.js +203 -95
  60. package/dist/react/index.js.map +1 -1
  61. package/dist/{types-cbe44b51.d.ts → types-2b26a246.d.ts} +23 -6
  62. package/package.json +1 -1
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var host_state_exports = {};
20
+ __export(host_state_exports, {
21
+ createHostState: () => createHostState
22
+ });
23
+ module.exports = __toCommonJS(host_state_exports);
24
+ function createHostState() {
25
+ return {
26
+ stage: "idle",
27
+ prevSrc: void 0,
28
+ prevUrl: void 0,
29
+ prevName: void 0,
30
+ prevIsRemoteComponent: false,
31
+ abortController: void 0
32
+ };
33
+ }
34
+ // Annotate the CommonJS export names for ESM import in node:
35
+ 0 && (module.exports = {
36
+ createHostState
37
+ });
38
+ //# sourceMappingURL=host-state.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/shared/contract/host-state.ts"],"sourcesContent":["/**\n * The lifecycle stages a host progresses through during a load cycle.\n *\n * ```\n * ┌─────────────────────────┐\n * │ (new load) │\n * ▼ │\n * idle ──▶ loading ──▶ loaded ─────────┘\n * ▲ │ │\n * │ ▼ │ (new load)\n * │ error ─────────┘\n * │\n * └── loading (abandoned / aborted)\n * ```\n *\n * - `idle` — No load has started, or a previous load was abandoned.\n * - `loading` — A fetch or hydration is in progress.\n * - `loaded` — The remote component rendered successfully.\n * - `error` — The load failed (the error itself is surfaced separately).\n *\n * Any non-idle stage transitions directly to `loading` when a new load starts.\n */\nexport type HostStage = 'idle' | 'loading' | 'loaded' | 'error';\n\n/**\n * Mutable state shared by every host implementation (HTML, React, Next.js\n * App Router).\n *\n * Each host stores a single `HostState` instance rather than scattering\n * individual properties/refs. This keeps the \"what changed since the last\n * load?\" tracking consistent across frameworks and makes it easy to test\n * state transitions in isolation.\n */\nexport interface HostState {\n /** Current lifecycle stage. */\n stage: HostStage;\n\n /** Source from the most-recent load. `undefined` before the first load. */\n prevSrc: string | URL | undefined;\n\n /** Resolved URL from the most-recent load. `undefined` before the first load. */\n prevUrl: URL | undefined;\n\n /** Component name from the most-recent load. `undefined` before the first load. */\n prevName: string | undefined;\n\n /** Whether the most-recent load was a remote component (vs. a plain page). */\n prevIsRemoteComponent: boolean;\n\n /**\n * `AbortController` for the in-flight load. Abort it to cancel a\n * superseded fetch. `undefined` when no load is active.\n */\n abortController: AbortController | undefined;\n}\n\n/** Creates a fresh `HostState` with all fields at their initial values. */\nexport function createHostState(): HostState {\n return {\n stage: 'idle',\n prevSrc: undefined,\n prevUrl: undefined,\n prevName: undefined,\n prevIsRemoteComponent: false,\n abortController: undefined,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDO,SAAS,kBAA6B;AAC3C,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,EACnB;AACF;","names":[]}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The lifecycle stages a host progresses through during a load cycle.
3
+ *
4
+ * ```
5
+ * ┌─────────────────────────┐
6
+ * │ (new load) │
7
+ * ▼ │
8
+ * idle ──▶ loading ──▶ loaded ─────────┘
9
+ * ▲ │ │
10
+ * │ ▼ │ (new load)
11
+ * │ error ─────────┘
12
+ * │
13
+ * └── loading (abandoned / aborted)
14
+ * ```
15
+ *
16
+ * - `idle` — No load has started, or a previous load was abandoned.
17
+ * - `loading` — A fetch or hydration is in progress.
18
+ * - `loaded` — The remote component rendered successfully.
19
+ * - `error` — The load failed (the error itself is surfaced separately).
20
+ *
21
+ * Any non-idle stage transitions directly to `loading` when a new load starts.
22
+ */
23
+ type HostStage = 'idle' | 'loading' | 'loaded' | 'error';
24
+ /**
25
+ * Mutable state shared by every host implementation (HTML, React, Next.js
26
+ * App Router).
27
+ *
28
+ * Each host stores a single `HostState` instance rather than scattering
29
+ * individual properties/refs. This keeps the "what changed since the last
30
+ * load?" tracking consistent across frameworks and makes it easy to test
31
+ * state transitions in isolation.
32
+ */
33
+ interface HostState {
34
+ /** Current lifecycle stage. */
35
+ stage: HostStage;
36
+ /** Source from the most-recent load. `undefined` before the first load. */
37
+ prevSrc: string | URL | undefined;
38
+ /** Resolved URL from the most-recent load. `undefined` before the first load. */
39
+ prevUrl: URL | undefined;
40
+ /** Component name from the most-recent load. `undefined` before the first load. */
41
+ prevName: string | undefined;
42
+ /** Whether the most-recent load was a remote component (vs. a plain page). */
43
+ prevIsRemoteComponent: boolean;
44
+ /**
45
+ * `AbortController` for the in-flight load. Abort it to cancel a
46
+ * superseded fetch. `undefined` when no load is active.
47
+ */
48
+ abortController: AbortController | undefined;
49
+ }
50
+ /** Creates a fresh `HostState` with all fields at their initial values. */
51
+ declare function createHostState(): HostState;
52
+
53
+ export { HostStage, HostState, createHostState };
@@ -0,0 +1,14 @@
1
+ function createHostState() {
2
+ return {
3
+ stage: "idle",
4
+ prevSrc: void 0,
5
+ prevUrl: void 0,
6
+ prevName: void 0,
7
+ prevIsRemoteComponent: false,
8
+ abortController: void 0
9
+ };
10
+ }
11
+ export {
12
+ createHostState
13
+ };
14
+ //# sourceMappingURL=host-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/shared/contract/host-state.ts"],"sourcesContent":["/**\n * The lifecycle stages a host progresses through during a load cycle.\n *\n * ```\n * ┌─────────────────────────┐\n * │ (new load) │\n * ▼ │\n * idle ──▶ loading ──▶ loaded ─────────┘\n * ▲ │ │\n * │ ▼ │ (new load)\n * │ error ─────────┘\n * │\n * └── loading (abandoned / aborted)\n * ```\n *\n * - `idle` — No load has started, or a previous load was abandoned.\n * - `loading` — A fetch or hydration is in progress.\n * - `loaded` — The remote component rendered successfully.\n * - `error` — The load failed (the error itself is surfaced separately).\n *\n * Any non-idle stage transitions directly to `loading` when a new load starts.\n */\nexport type HostStage = 'idle' | 'loading' | 'loaded' | 'error';\n\n/**\n * Mutable state shared by every host implementation (HTML, React, Next.js\n * App Router).\n *\n * Each host stores a single `HostState` instance rather than scattering\n * individual properties/refs. This keeps the \"what changed since the last\n * load?\" tracking consistent across frameworks and makes it easy to test\n * state transitions in isolation.\n */\nexport interface HostState {\n /** Current lifecycle stage. */\n stage: HostStage;\n\n /** Source from the most-recent load. `undefined` before the first load. */\n prevSrc: string | URL | undefined;\n\n /** Resolved URL from the most-recent load. `undefined` before the first load. */\n prevUrl: URL | undefined;\n\n /** Component name from the most-recent load. `undefined` before the first load. */\n prevName: string | undefined;\n\n /** Whether the most-recent load was a remote component (vs. a plain page). */\n prevIsRemoteComponent: boolean;\n\n /**\n * `AbortController` for the in-flight load. Abort it to cancel a\n * superseded fetch. `undefined` when no load is active.\n */\n abortController: AbortController | undefined;\n}\n\n/** Creates a fresh `HostState` with all fields at their initial values. */\nexport function createHostState(): HostState {\n return {\n stage: 'idle',\n prevSrc: undefined,\n prevUrl: undefined,\n prevName: undefined,\n prevIsRemoteComponent: false,\n abortController: undefined,\n };\n}\n"],"mappings":"AAyDO,SAAS,kBAA6B;AAC3C,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,EACnB;AACF;","names":[]}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var resolve_name_from_src_exports = {};
20
+ __export(resolve_name_from_src_exports, {
21
+ resolveNameFromSrc: () => resolveNameFromSrc
22
+ });
23
+ module.exports = __toCommonJS(resolve_name_from_src_exports);
24
+ function resolveNameFromSrc(src, defaultName) {
25
+ if (!src) {
26
+ return defaultName;
27
+ }
28
+ const hash = typeof src === "string" ? src : src.hash;
29
+ const hashIndex = hash.indexOf("#");
30
+ if (hashIndex < 0) {
31
+ return defaultName;
32
+ }
33
+ const name = hash.slice(hashIndex + 1);
34
+ return name || defaultName;
35
+ }
36
+ // Annotate the CommonJS export names for ESM import in node:
37
+ 0 && (module.exports = {
38
+ resolveNameFromSrc
39
+ });
40
+ //# sourceMappingURL=resolve-name-from-src.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/shared/contract/resolve-name-from-src.ts"],"sourcesContent":["/**\n * Extracts a component name from the URL hash of `src`, falling back to\n * `defaultName` when no hash is present.\n *\n * Both the HTML and React hosts use this to derive the component name\n * from patterns like `/components/header#my-component`.\n *\n * Parses the hash directly from the string rather than constructing a\n * full `URL`, so no SSR fallback base is needed.\n */\nexport function resolveNameFromSrc(\n src: string | URL | undefined,\n defaultName: string,\n): string {\n if (!src) {\n return defaultName;\n }\n\n const hash = typeof src === 'string' ? src : src.hash;\n const hashIndex = hash.indexOf('#');\n if (hashIndex < 0) {\n return defaultName;\n }\n\n const name = hash.slice(hashIndex + 1);\n return name || defaultName;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,SAAS,mBACd,KACA,aACQ;AACR,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,QAAQ,WAAW,MAAM,IAAI;AACjD,QAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,MAAI,YAAY,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,KAAK,MAAM,YAAY,CAAC;AACrC,SAAO,QAAQ;AACjB;","names":[]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Extracts a component name from the URL hash of `src`, falling back to
3
+ * `defaultName` when no hash is present.
4
+ *
5
+ * Both the HTML and React hosts use this to derive the component name
6
+ * from patterns like `/components/header#my-component`.
7
+ *
8
+ * Parses the hash directly from the string rather than constructing a
9
+ * full `URL`, so no SSR fallback base is needed.
10
+ */
11
+ declare function resolveNameFromSrc(src: string | URL | undefined, defaultName: string): string;
12
+
13
+ export { resolveNameFromSrc };
@@ -0,0 +1,16 @@
1
+ function resolveNameFromSrc(src, defaultName) {
2
+ if (!src) {
3
+ return defaultName;
4
+ }
5
+ const hash = typeof src === "string" ? src : src.hash;
6
+ const hashIndex = hash.indexOf("#");
7
+ if (hashIndex < 0) {
8
+ return defaultName;
9
+ }
10
+ const name = hash.slice(hashIndex + 1);
11
+ return name || defaultName;
12
+ }
13
+ export {
14
+ resolveNameFromSrc
15
+ };
16
+ //# sourceMappingURL=resolve-name-from-src.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/shared/contract/resolve-name-from-src.ts"],"sourcesContent":["/**\n * Extracts a component name from the URL hash of `src`, falling back to\n * `defaultName` when no hash is present.\n *\n * Both the HTML and React hosts use this to derive the component name\n * from patterns like `/components/header#my-component`.\n *\n * Parses the hash directly from the string rather than constructing a\n * full `URL`, so no SSR fallback base is needed.\n */\nexport function resolveNameFromSrc(\n src: string | URL | undefined,\n defaultName: string,\n): string {\n if (!src) {\n return defaultName;\n }\n\n const hash = typeof src === 'string' ? src : src.hash;\n const hashIndex = hash.indexOf('#');\n if (hashIndex < 0) {\n return defaultName;\n }\n\n const name = hash.slice(hashIndex + 1);\n return name || defaultName;\n}\n"],"mappings":"AAUO,SAAS,mBACd,KACA,aACQ;AACR,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,QAAQ,WAAW,MAAM,IAAI;AACjD,QAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,MAAI,YAAY,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,KAAK,MAAM,YAAY,CAAC;AACrC,SAAO,QAAQ;AACjB;","names":[]}
@@ -1,2 +1,2 @@
1
1
  import 'parse5/dist/tree-adapters/default';
2
- export { C as Context, b as RSC, v as visit } from '../../../types-cbe44b51.js';
2
+ export { C as Context, b as RSC, v as visit } from '../../../types-2b26a246.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { fetchWithHooks } from '#internal/shared/ssr/fetch-with-hooks';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport {\n getSkeletonHtml,\n getSkeletonMessage,\n} from '#internal/shared/ssr/skeleton';\nimport type {\n FetchRemoteComponentResponse,\n NextData,\n OnRequestHook,\n OnResponseHook,\n RemoteComponentMetadata,\n} from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n options: {\n name?: string;\n rsc?: boolean;\n /** Whether this is being called from Next.js App Router. Used to enable skeleton fallback during SSG builds. */\n appRouter?: boolean;\n onRequest?: OnRequestHook;\n onResponse?: OnResponseHook;\n } = {\n rsc: false,\n },\n): Promise<FetchRemoteComponentResponse> {\n const ssrRelativePathBaseUrl = getSSRRelativePathBaseUrl();\n const serverUrl = new URL(src, ssrRelativePathBaseUrl);\n\n const tags = [\n '_vc_rc:fetch-remote-component',\n // the max size of a next cache tag is 256 characters\n serverUrl.host.slice(0, 256),\n // use the suffix so this tag is unique if multiple remote\n // components have the same host, but unique pathnames / query params\n (typeof src === 'string' ? src : src.href).slice(-256),\n ];\n if (options.name) {\n tags.push(options.name.slice(-256));\n }\n\n const fetchInit = {\n next: {\n tags,\n },\n };\n\n const res = await fetchWithHooks(serverUrl, fetchInit, {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n });\n\n // If there is an error in the remote, parse and extract the remote error (except 404 and 401).\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(serverUrl.href, res);\n }\n\n if (res.status === 401) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'If you are using Deployment Protection, ensure the automation bypass environment variable secret in the host matches an automation bypass value in the remote. See https://remote-components-docs.vercel.sh/docs/concepts/cors-external-urls#deployment-protection for details.',\n );\n }\n\n if (res.status === 404) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'Check if you can open it in the browser.',\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `Response body is empty. Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData: NextData | undefined;\n let html = '';\n\n const remoteName =\n options.name || (serverUrl.hash ? serverUrl.hash.substring(1) : undefined);\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: RemoteComponentsError | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n // Skip multiple component detection for Pages Router (__next) since it only supports one remote component per page\n if (\n hasRemoteComponent &&\n metadata.id !== _metadata.id &&\n _metadata.id !== '__next' &&\n metadata.id !== '__next' &&\n !nextData\n ) {\n hasMultipleRemoteComponents = true;\n }\n metadata = _metadata;\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n // For microfrontend builds during run time, the host and remote build\n // may be happening concurrently. In this case, the request will 404.\n // We want to allow the build to continue with a placeholder remote\n // component. Once the build completes, vercel will automatically revalidate\n // ISR and fetch the built remote component.\n const isSSGBuild = process.env.NEXT_PHASE === 'phase-production-build';\n // If the remote component is part of a microfrontend, the src provided\n // will be relative.\n const isSSRRelativePathBase =\n serverUrl.host === new URL(ssrRelativePathBaseUrl).host;\n // Only want this skeleton behaviour in previews to unblock development.\n // For production, the remote component should already be built.\n const isPreview = process.env.VERCEL_TARGET_ENV === 'preview';\n\n if (isSSGBuild && isSSRRelativePathBase && isPreview && options.appRouter) {\n const skeletonMessage = getSkeletonMessage();\n const skeletonHtml = getSkeletonHtml(serverUrl.href);\n\n let skeletonComponent: React.ReactNode | undefined;\n if (options.rsc) {\n const { createElement } = await import('react');\n skeletonComponent = createElement('div', {\n dangerouslySetInnerHTML: { __html: skeletonHtml },\n });\n }\n\n return {\n name: 'remote-component-skeleton',\n serverUrl,\n metadata: {\n ...metadata,\n type: 'remote-component',\n },\n rsc: skeletonMessage,\n scripts: [],\n links: [],\n hydrationData: [],\n nextData: undefined,\n component: skeletonComponent,\n html: skeletonHtml,\n remoteShared: {},\n };\n }\n\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `No Remote Component found. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new RemoteComponentsError(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new RemoteComponentsError(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n return {\n name: remoteName || metadata.id.replace(/_ssr$/, ''),\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport type {\n LinkDescriptor,\n ScriptDescriptor,\n} from '#internal/shared/contract/payload';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { fetchWithHooks } from '#internal/shared/ssr/fetch-with-hooks';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport {\n getSkeletonHtml,\n getSkeletonMessage,\n} from '#internal/shared/ssr/skeleton';\nimport type {\n FetchRemoteComponentResponse,\n NextData,\n OnRequestHook,\n OnResponseHook,\n RemoteComponentMetadata,\n} from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n options: {\n name?: string;\n rsc?: boolean;\n /** Whether this is being called from Next.js App Router. Used to enable skeleton fallback during SSG builds. */\n appRouter?: boolean;\n onRequest?: OnRequestHook;\n onResponse?: OnResponseHook;\n } = {\n rsc: false,\n },\n): Promise<FetchRemoteComponentResponse> {\n const ssrRelativePathBaseUrl = getSSRRelativePathBaseUrl();\n const serverUrl = new URL(src, ssrRelativePathBaseUrl);\n\n const tags = [\n '_vc_rc:fetch-remote-component',\n // the max size of a next cache tag is 256 characters\n serverUrl.host.slice(0, 256),\n // use the suffix so this tag is unique if multiple remote\n // components have the same host, but unique pathnames / query params\n (typeof src === 'string' ? src : src.href).slice(-256),\n ];\n if (options.name) {\n tags.push(options.name.slice(-256));\n }\n\n const fetchInit = {\n next: {\n tags,\n },\n };\n\n const res = await fetchWithHooks(serverUrl, fetchInit, {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n });\n\n // If there is an error in the remote, parse and extract the remote error (except 404 and 401).\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(serverUrl.href, res);\n }\n\n if (res.status === 401) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'If you are using Deployment Protection, ensure the automation bypass environment variable secret in the host matches an automation bypass value in the remote. See https://remote-components-docs.vercel.sh/docs/concepts/cors-external-urls#deployment-protection for details.',\n );\n }\n\n if (res.status === 404) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'Check if you can open it in the browser.',\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `Response body is empty. Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: ScriptDescriptor[] = [];\n const links: LinkDescriptor[] = [];\n const hydrationData: string[] = [];\n let nextData: NextData | undefined;\n let html = '';\n\n const remoteName =\n options.name || (serverUrl.hash ? serverUrl.hash.substring(1) : undefined);\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: RemoteComponentsError | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n // Skip multiple component detection for Pages Router (__next) since it only supports one remote component per page\n if (\n hasRemoteComponent &&\n metadata.id !== _metadata.id &&\n _metadata.id !== '__next' &&\n metadata.id !== '__next' &&\n !nextData\n ) {\n hasMultipleRemoteComponents = true;\n }\n metadata = _metadata;\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n // For microfrontend builds during run time, the host and remote build\n // may be happening concurrently. In this case, the request will 404.\n // We want to allow the build to continue with a placeholder remote\n // component. Once the build completes, vercel will automatically revalidate\n // ISR and fetch the built remote component.\n const isSSGBuild = process.env.NEXT_PHASE === 'phase-production-build';\n // If the remote component is part of a microfrontend, the src provided\n // will be relative.\n const isSSRRelativePathBase =\n serverUrl.host === new URL(ssrRelativePathBaseUrl).host;\n // Only want this skeleton behaviour in previews to unblock development.\n // For production, the remote component should already be built.\n const isPreview = process.env.VERCEL_TARGET_ENV === 'preview';\n\n if (isSSGBuild && isSSRRelativePathBase && isPreview && options.appRouter) {\n const skeletonMessage = getSkeletonMessage();\n const skeletonHtml = getSkeletonHtml(serverUrl.href);\n\n let skeletonComponent: React.ReactNode | undefined;\n if (options.rsc) {\n const { createElement } = await import('react');\n skeletonComponent = createElement('div', {\n dangerouslySetInnerHTML: { __html: skeletonHtml },\n });\n }\n\n return {\n name: 'remote-component-skeleton',\n serverUrl,\n metadata: {\n ...metadata,\n type: 'remote-component',\n },\n rsc: skeletonMessage,\n scripts: [],\n links: [],\n hydrationData: [],\n nextData: undefined,\n component: skeletonComponent,\n html: skeletonHtml,\n remoteShared: {},\n };\n }\n\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `No Remote Component found. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new RemoteComponentsError(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new RemoteComponentsError(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n return {\n name: remoteName || metadata.id.replace(/_ssr$/, ''),\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { O as OnRequestHook, a as OnResponseHook, F as FetchRemoteComponentResponse } from '../../../types-cbe44b51.js';
1
+ import { O as OnRequestHook, a as OnResponseHook, F as FetchRemoteComponentResponse } from '../../../types-2b26a246.js';
2
2
  import 'parse5/dist/tree-adapters/default';
3
3
 
4
4
  declare function fetchRemoteComponent(src: string | URL, options?: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { fetchWithHooks } from '#internal/shared/ssr/fetch-with-hooks';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport {\n getSkeletonHtml,\n getSkeletonMessage,\n} from '#internal/shared/ssr/skeleton';\nimport type {\n FetchRemoteComponentResponse,\n NextData,\n OnRequestHook,\n OnResponseHook,\n RemoteComponentMetadata,\n} from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n options: {\n name?: string;\n rsc?: boolean;\n /** Whether this is being called from Next.js App Router. Used to enable skeleton fallback during SSG builds. */\n appRouter?: boolean;\n onRequest?: OnRequestHook;\n onResponse?: OnResponseHook;\n } = {\n rsc: false,\n },\n): Promise<FetchRemoteComponentResponse> {\n const ssrRelativePathBaseUrl = getSSRRelativePathBaseUrl();\n const serverUrl = new URL(src, ssrRelativePathBaseUrl);\n\n const tags = [\n '_vc_rc:fetch-remote-component',\n // the max size of a next cache tag is 256 characters\n serverUrl.host.slice(0, 256),\n // use the suffix so this tag is unique if multiple remote\n // components have the same host, but unique pathnames / query params\n (typeof src === 'string' ? src : src.href).slice(-256),\n ];\n if (options.name) {\n tags.push(options.name.slice(-256));\n }\n\n const fetchInit = {\n next: {\n tags,\n },\n };\n\n const res = await fetchWithHooks(serverUrl, fetchInit, {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n });\n\n // If there is an error in the remote, parse and extract the remote error (except 404 and 401).\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(serverUrl.href, res);\n }\n\n if (res.status === 401) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'If you are using Deployment Protection, ensure the automation bypass environment variable secret in the host matches an automation bypass value in the remote. See https://remote-components-docs.vercel.sh/docs/concepts/cors-external-urls#deployment-protection for details.',\n );\n }\n\n if (res.status === 404) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'Check if you can open it in the browser.',\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `Response body is empty. Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData: NextData | undefined;\n let html = '';\n\n const remoteName =\n options.name || (serverUrl.hash ? serverUrl.hash.substring(1) : undefined);\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: RemoteComponentsError | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n // Skip multiple component detection for Pages Router (__next) since it only supports one remote component per page\n if (\n hasRemoteComponent &&\n metadata.id !== _metadata.id &&\n _metadata.id !== '__next' &&\n metadata.id !== '__next' &&\n !nextData\n ) {\n hasMultipleRemoteComponents = true;\n }\n metadata = _metadata;\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n // For microfrontend builds during run time, the host and remote build\n // may be happening concurrently. In this case, the request will 404.\n // We want to allow the build to continue with a placeholder remote\n // component. Once the build completes, vercel will automatically revalidate\n // ISR and fetch the built remote component.\n const isSSGBuild = process.env.NEXT_PHASE === 'phase-production-build';\n // If the remote component is part of a microfrontend, the src provided\n // will be relative.\n const isSSRRelativePathBase =\n serverUrl.host === new URL(ssrRelativePathBaseUrl).host;\n // Only want this skeleton behaviour in previews to unblock development.\n // For production, the remote component should already be built.\n const isPreview = process.env.VERCEL_TARGET_ENV === 'preview';\n\n if (isSSGBuild && isSSRRelativePathBase && isPreview && options.appRouter) {\n const skeletonMessage = getSkeletonMessage();\n const skeletonHtml = getSkeletonHtml(serverUrl.href);\n\n let skeletonComponent: React.ReactNode | undefined;\n if (options.rsc) {\n const { createElement } = await import('react');\n skeletonComponent = createElement('div', {\n dangerouslySetInnerHTML: { __html: skeletonHtml },\n });\n }\n\n return {\n name: 'remote-component-skeleton',\n serverUrl,\n metadata: {\n ...metadata,\n type: 'remote-component',\n },\n rsc: skeletonMessage,\n scripts: [],\n links: [],\n hydrationData: [],\n nextData: undefined,\n component: skeletonComponent,\n html: skeletonHtml,\n remoteShared: {},\n };\n }\n\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `No Remote Component found. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new RemoteComponentsError(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new RemoteComponentsError(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n return {\n name: remoteName || metadata.id.replace(/_ssr$/, ''),\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport type {\n LinkDescriptor,\n ScriptDescriptor,\n} from '#internal/shared/contract/payload';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { fetchWithHooks } from '#internal/shared/ssr/fetch-with-hooks';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport {\n getSkeletonHtml,\n getSkeletonMessage,\n} from '#internal/shared/ssr/skeleton';\nimport type {\n FetchRemoteComponentResponse,\n NextData,\n OnRequestHook,\n OnResponseHook,\n RemoteComponentMetadata,\n} from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n options: {\n name?: string;\n rsc?: boolean;\n /** Whether this is being called from Next.js App Router. Used to enable skeleton fallback during SSG builds. */\n appRouter?: boolean;\n onRequest?: OnRequestHook;\n onResponse?: OnResponseHook;\n } = {\n rsc: false,\n },\n): Promise<FetchRemoteComponentResponse> {\n const ssrRelativePathBaseUrl = getSSRRelativePathBaseUrl();\n const serverUrl = new URL(src, ssrRelativePathBaseUrl);\n\n const tags = [\n '_vc_rc:fetch-remote-component',\n // the max size of a next cache tag is 256 characters\n serverUrl.host.slice(0, 256),\n // use the suffix so this tag is unique if multiple remote\n // components have the same host, but unique pathnames / query params\n (typeof src === 'string' ? src : src.href).slice(-256),\n ];\n if (options.name) {\n tags.push(options.name.slice(-256));\n }\n\n const fetchInit = {\n next: {\n tags,\n },\n };\n\n const res = await fetchWithHooks(serverUrl, fetchInit, {\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n });\n\n // If there is an error in the remote, parse and extract the remote error (except 404 and 401).\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(serverUrl.href, res);\n }\n\n if (res.status === 401) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'If you are using Deployment Protection, ensure the automation bypass environment variable secret in the host matches an automation bypass value in the remote. See https://remote-components-docs.vercel.sh/docs/concepts/cors-external-urls#deployment-protection for details.',\n );\n }\n\n if (res.status === 404) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n 'Check if you can open it in the browser.',\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `Response body is empty. Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: ScriptDescriptor[] = [];\n const links: LinkDescriptor[] = [];\n const hydrationData: string[] = [];\n let nextData: NextData | undefined;\n let html = '';\n\n const remoteName =\n options.name || (serverUrl.hash ? serverUrl.hash.substring(1) : undefined);\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: RemoteComponentsError | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n // Skip multiple component detection for Pages Router (__next) since it only supports one remote component per page\n if (\n hasRemoteComponent &&\n metadata.id !== _metadata.id &&\n _metadata.id !== '__next' &&\n metadata.id !== '__next' &&\n !nextData\n ) {\n hasMultipleRemoteComponents = true;\n }\n metadata = _metadata;\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n // For microfrontend builds during run time, the host and remote build\n // may be happening concurrently. In this case, the request will 404.\n // We want to allow the build to continue with a placeholder remote\n // component. Once the build completes, vercel will automatically revalidate\n // ISR and fetch the built remote component.\n const isSSGBuild = process.env.NEXT_PHASE === 'phase-production-build';\n // If the remote component is part of a microfrontend, the src provided\n // will be relative.\n const isSSRRelativePathBase =\n serverUrl.host === new URL(ssrRelativePathBaseUrl).host;\n // Only want this skeleton behaviour in previews to unblock development.\n // For production, the remote component should already be built.\n const isPreview = process.env.VERCEL_TARGET_ENV === 'preview';\n\n if (isSSGBuild && isSSRRelativePathBase && isPreview && options.appRouter) {\n const skeletonMessage = getSkeletonMessage();\n const skeletonHtml = getSkeletonHtml(serverUrl.href);\n\n let skeletonComponent: React.ReactNode | undefined;\n if (options.rsc) {\n const { createElement } = await import('react');\n skeletonComponent = createElement('div', {\n dangerouslySetInnerHTML: { __html: skeletonHtml },\n });\n }\n\n return {\n name: 'remote-component-skeleton',\n serverUrl,\n metadata: {\n ...metadata,\n type: 'remote-component',\n },\n rsc: skeletonMessage,\n scripts: [],\n links: [],\n hydrationData: [],\n nextData: undefined,\n component: skeletonComponent,\n html: skeletonHtml,\n remoteShared: {},\n };\n }\n\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n res,\n `No Remote Component found. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new RemoteComponentsError(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new RemoteComponentsError(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n return {\n name: remoteName || metadata.id.replace(/_ssr$/, ''),\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"AAAA,SAAqC,cAAc;AACnD,SAAS,oBAAoB;AAK7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAC/B,SAAS,iCAAiC;AAC1C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AASP,MAAM,eAAe,QAAQ,IAAI;AAEjC,eAAsB,qBACpB,KACA,UAOI;AAAA,EACF,KAAK;AACP,GACuC;AACvC,QAAM,yBAAyB,0BAA0B;AACzD,QAAM,YAAY,IAAI,IAAI,KAAK,sBAAsB;AAErD,QAAM,OAAO;AAAA,IACX;AAAA;AAAA,IAEA,UAAU,KAAK,MAAM,GAAG,GAAG;AAAA;AAAA;AAAA,KAG1B,OAAO,QAAQ,WAAW,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,EACvD;AACA,MAAI,QAAQ,MAAM;AAChB,SAAK,KAAK,QAAQ,KAAK,MAAM,IAAI,CAAC;AAAA,EACpC;AAEA,QAAM,YAAY;AAAA,IAChB,MAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,MAAM,eAAe,WAAW,WAAW;AAAA,IACrD,WAAW,QAAQ;AAAA,IACnB,YAAY,QAAQ;AAAA,EACtB,CAAC;AAGD,MAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;AACxB,UAAM,kCAAkC,UAAU,MAAM,GAAG;AAAA,EAC7D;AAEA,MAAI,IAAI,WAAW,KAAK;AACtB,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,WAAW,KAAK;AACtB,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,OAAO,kBAAyC;AAE/D,MAAI,CAAC,IAAI,MAAM;AACb,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,YAAY;AAEhC,mBAAiB,SAAS,IAAI,MAA8C;AAC1E,WAAO,UAAU,MAAM,QAAQ,OAAO,KAAK,GAAG,KAAK;AAAA,EACrD;AACA,QAAM,WAAW,OAAO,YAAY;AAEpC,MAAI,WAAoC;AAAA,IACtC,QAAQ,gBAAgB;AAAA,IACxB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,EACR;AACA,MAAI,eAAuC,CAAC;AAC5C,QAAM,UAA8B,CAAC;AACrC,QAAM,QAA0B,CAAC;AACjC,QAAM,gBAA0B,CAAC;AACjC,MAAI;AACJ,MAAI,OAAO;AAEX,QAAM,aACJ,QAAQ,SAAS,UAAU,OAAO,UAAU,KAAK,UAAU,CAAC,IAAI;AAGlE,MAAI,qBAAqB;AACzB,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,MAAI,8BAA8B;AAClC,MAAI;AACJ,QAAM,MAAM,MAAM,UAAU;AAAA,IAC1B,KAAK;AAAA,IACL,MAAM;AAAA,IACN,WAAW,WAAW;AAEpB,UACE,sBACA,SAAS,OAAO,UAAU,MAC1B,UAAU,OAAO,YACjB,SAAS,OAAO,YAChB,CAAC,UACD;AACA,sCAA8B;AAAA,MAChC;AACA,iBAAW;AACX,2BAAqB;AAAA,IACvB;AAAA,IACA,SAAS,OAAO;AACd,YAAM,YAAY,aAAa,MAAM,KAAK,UAAU,IAAI;AACxD,UACE,CAAC,QAAQ;AAAA,QACP,CAAC,OACC,GAAG,QAAQ,aACV,MAAM,eAAe,GAAG,gBAAgB,MAAM;AAAA,MACnD,GACA;AACA,gBAAQ;AAAA,UACN,OAAO,MAAM,gBAAgB,WACzB;AAAA,YACE,KAAK;AAAA,YACL,aAAa,MAAM;AAAA,UACrB,IACA;AAAA,YACE,KAAK;AAAA,UACP;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO,OAAO;AACZ,YAAM,gBAAgB;AAAA,QACpB,GAAG;AAAA,QACH,MAAM,aAAa,MAAM,MAAM,UAAU,IAAI;AAAA,MAC/C;AACA,UACE,CAAC,MAAM;AAAA,QACL,CAAC,OAAO,GAAG,SAAS,cAAc,QAAQ,GAAG,QAAQ,MAAM;AAAA,MAC7D,GACA;AACA,cAAM,KAAK,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,MAAM,OAAO;AACX,oBAAc,KAAK,KAAK;AACxB,eAAS;AAAA,IACX;AAAA,IACA,WAAW,MAAM;AACf,iBAAW;AAGX,UAAI,KAAK,MAAM,sBAAsB;AACnC,eAAO,OAAO,UAAU,KAAK,MAAM,oBAAoB;AAEvD,iBAAS,KAAK;AACd,iBAAS,QAAQ,KAAK,QAAQ;AAAA,MAChC;AAAA,IACF;AAAA,IACA,OAAO,OAAO;AACZ,UAAI,CAAC,KAAK,SAAS,KAAK,GAAG;AACzB,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,SAAS,SAAS;AAChB,qBAAe;AACf,kBAAY;AAAA,IACd;AAAA,IACA,QAAQ,SAAS,OAAO;AACtB,cAAQ,IAAI,sBAAsB,OAAO;AACzC,UAAI,OAAO;AACT,cAAM,QAAQ;AAAA,MAChB;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,OAAO;AACT,UAAM;AAAA,EACR;AAGA,MAAI,CAAC,oBAAoB;AAMvB,UAAM,aAAa,QAAQ,IAAI,eAAe;AAG9C,UAAM,wBACJ,UAAU,SAAS,IAAI,IAAI,sBAAsB,EAAE;AAGrD,UAAM,YAAY,QAAQ,IAAI,sBAAsB;AAEpD,QAAI,cAAc,yBAAyB,aAAa,QAAQ,WAAW;AACzE,YAAM,kBAAkB,mBAAmB;AAC3C,YAAM,eAAe,gBAAgB,UAAU,IAAI;AAEnD,UAAI;AACJ,UAAI,QAAQ,KAAK;AACf,cAAM,EAAE,cAAc,IAAI,MAAM,OAAO,OAAO;AAC9C,4BAAoB,cAAc,OAAO;AAAA,UACvC,yBAAyB,EAAE,QAAQ,aAAa;AAAA,QAClD,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,UAAU;AAAA,UACR,GAAG;AAAA,UACH,MAAM;AAAA,QACR;AAAA,QACA,KAAK;AAAA,QACL,SAAS,CAAC;AAAA,QACV,OAAO,CAAC;AAAA,QACR,eAAe,CAAC;AAAA,QAChB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,MAAM;AAAA,QACN,cAAc,CAAC;AAAA,MACjB;AAAA,IACF;AAEA,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,MAAI,+BAA+B,CAAC,YAAY;AAC9C,UAAM,8BAA8B,UAAU,IAAI;AAAA,EACpD;AAGA,MAAI,CAAC,UAAU,CAAC,YAAY,SAAS,SAAS,UAAU;AACtD,UAAM,IAAI;AAAA,MACR,4BAA4B,UAAU;AAAA,IACxC;AAAA,EACF;AAEA,MACE,SAAS,SAAS;AAAA,EAElB,CAAC,aACD,CAAC,UAAU,MAAM,sBAAsB,QACvC;AACA,UAAM,IAAI;AAAA,MACR,yDAAyD,UAAU;AAAA,IACrE;AAAA,EACF;AAEA,MAAI;AAGJ,MAAI,QAAQ,KAAK;AAEf,UAAM,eAAe,KAAK,KAAK,UAAU,GAAG;AAAA;AAE5C,UAAM,EAAE,yBAAyB,IAAI,MAAM,OACzC,yDACF;AAGA,gBAAY,MAAM;AAAA,MAChB,IAAI,eAAe;AAAA,QACjB,MAAM;AAAA,QACN,MAAM,YAAY;AAChB,gBAAM,UAAU,IAAI,YAAY;AAChC,qBAAW,QAAQ,QAAQ,OAAO,YAAY,CAAC;AAC/C,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,MACD;AAAA,QACE,wBAAwB;AAAA,UACtB,eAAe;AAAA,YACb,QAAQ,UAAU;AAAA,YAClB,aAAa;AAAA,UACf;AAAA,UACA,WAAW,CAAC;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,SAAS,GAAG,QAAQ,SAAS,EAAE;AAAA,IACnD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,UAAU,MAAM,sBAAsB,UAAU;AAAA,EAChE;AACF;","names":[]}
@@ -1,4 +1,4 @@
1
- import { O as OnRequestHook, a as OnResponseHook } from '../../../types-cbe44b51.js';
1
+ import { O as OnRequestHook, a as OnResponseHook } from '../../../types-2b26a246.js';
2
2
  import 'parse5/dist/tree-adapters/default';
3
3
 
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/next/host/app-router-server.tsx"],"sourcesContent":["import { Children, Suspense } from 'react';\nimport { RemoteComponentClient } from '#internal/next/host/app-router-client';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport type { OnRequestHook, OnResponseHook } from '#internal/shared/ssr/types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport interface RemoteComponentProps {\n /** The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported. */\n src: string | URL;\n /** The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page. */\n name?: string;\n /** Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation. */\n isolate?: boolean;\n /** The mode of the Shadow DOM. Defaults to `open`. */\n mode?: 'open' | 'closed';\n /** Whether to include a CSS reset style in the shadow DOM. Defaults to `false`. */\n reset?: boolean;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n /**\n * Called when a fetch request is made to retrieve the remote component payload.\n * Can be used to intercept requests, modify headers, or provide a custom response.\n */\n onRequest?: OnRequestHook;\n /**\n * Called after a fetch completes to retrieve the remote component payload.\n * Can be used to inspect the response (e.g., check for redirects) or transform it.\n */\n onResponse?: OnResponseHook;\n}\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param name - The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @param mode - The mode of the Shadow DOM. Defaults to `open`.\n * @param reset - Whether to include a CSS reset style in the shadow DOM. Defaults to `false`.\n * @param children - Loading fallback content to display while the remote component is being fetched.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: RemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n const remoteComponentClient = (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n type={metadata.type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </RemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8FI;AA9FJ,mBAAmC;AACnC,+BAAsC;AACtC,oCAAqC;AAGrC,MAAM,eAAe,QAAQ,IAAI;AAyDjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsD;AACpD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,UAAM,oDAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,MAAM,SAAS;AAAA,MACf,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,sBAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,4CAAC,yBAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/next/host/app-router-server.tsx"],"sourcesContent":["import { Children, Suspense } from 'react';\nimport { RemoteComponentClient } from '#internal/next/host/app-router-client';\nimport type { HostConfig } from '#internal/shared/contract/host-config';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface RemoteComponentProps extends HostConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link RemoteComponentProps} (extends {@link HostConfig}).\n *\n * @example\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return <RemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: RemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n const remoteComponentClient = (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n type={metadata.type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </RemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DI;AA9DJ,mBAAmC;AACnC,+BAAsC;AAEtC,oCAAqC;AAErC,MAAM,eAAe,QAAQ,IAAI;AAyBjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsD;AACpD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,UAAM,oDAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,MAAM,SAAS;AAAA,MACf,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,sBAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,4CAAC,yBAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}
@@ -1,57 +1,27 @@
1
- import { O as OnRequestHook, a as OnResponseHook } from '../../types-cbe44b51.js';
1
+ import { H as HostConfig } from '../../host-config-58cdccea.js';
2
+ import '../../internal/shared/client/proxy-through-host.js';
3
+ import '../../types-2b26a246.js';
2
4
  import 'parse5/dist/tree-adapters/default';
3
5
 
4
- interface RemoteComponentProps {
5
- /** The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported. */
6
+ /**
7
+ * Props for the Next.js App Router remote component host (server component).
8
+ */
9
+ interface RemoteComponentProps extends HostConfig {
10
+ /** The source URL of the remote component. Required for server rendering. */
6
11
  src: string | URL;
7
- /** The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page. */
8
- name?: string;
9
- /** Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation. */
10
- isolate?: boolean;
11
- /** The mode of the Shadow DOM. Defaults to `open`. */
12
- mode?: 'open' | 'closed';
13
- /** Whether to include a CSS reset style in the shadow DOM. Defaults to `false`. */
14
- reset?: boolean;
15
12
  /** Loading fallback content to display while the remote component is being fetched. */
16
13
  children?: React.ReactNode;
17
- /**
18
- * Called when a fetch request is made to retrieve the remote component payload.
19
- * Can be used to intercept requests, modify headers, or provide a custom response.
20
- */
21
- onRequest?: OnRequestHook;
22
- /**
23
- * Called after a fetch completes to retrieve the remote component payload.
24
- * Can be used to inspect the response (e.g., check for redirects) or transform it.
25
- */
26
- onResponse?: OnResponseHook;
27
14
  }
28
15
  /**
29
- * RemoteComponent is a Next.js component that fetches and renders a remote component.
30
- * It supports SSR and can isolate the remote component in a shadow DOM.
31
- *
32
- * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.
33
- * @param name - The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page.
34
- * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.
35
- * @param mode - The mode of the Shadow DOM. Defaults to `open`.
36
- * @param reset - Whether to include a CSS reset style in the shadow DOM. Defaults to `false`.
37
- * @param children - Loading fallback content to display while the remote component is being fetched.
38
- * @returns A React component that renders the remote component.
16
+ * Next.js App Router server component that fetches and renders a remote component.
17
+ * Props are documented on {@link RemoteComponentProps} (extends {@link HostConfig}).
39
18
  *
40
19
  * @example
41
- *
42
- * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:
43
- *
44
20
  * ```tsx
45
21
  * import { RemoteComponent } from 'remote-components/next/host';
46
22
  *
47
23
  * export default function MyPage() {
48
- * return (
49
- * <>
50
- * <h1>Welcome to My Page</h1>
51
- * <p>This page consumes a remote component from another application.</p>
52
- * <RemoteComponent src="/nextjs-app-remote/components/header" />
53
- * </>
54
- * );
24
+ * return <RemoteComponent src="/nextjs-app-remote/components/header" />;
55
25
  * }
56
26
  * ```
57
27
  */
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/next/host/app-router-server.tsx"],"sourcesContent":["import { Children, Suspense } from 'react';\nimport { RemoteComponentClient } from '#internal/next/host/app-router-client';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport type { OnRequestHook, OnResponseHook } from '#internal/shared/ssr/types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\nexport interface RemoteComponentProps {\n /** The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported. */\n src: string | URL;\n /** The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page. */\n name?: string;\n /** Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation. */\n isolate?: boolean;\n /** The mode of the Shadow DOM. Defaults to `open`. */\n mode?: 'open' | 'closed';\n /** Whether to include a CSS reset style in the shadow DOM. Defaults to `false`. */\n reset?: boolean;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n /**\n * Called when a fetch request is made to retrieve the remote component payload.\n * Can be used to intercept requests, modify headers, or provide a custom response.\n */\n onRequest?: OnRequestHook;\n /**\n * Called after a fetch completes to retrieve the remote component payload.\n * Can be used to inspect the response (e.g., check for redirects) or transform it.\n */\n onResponse?: OnResponseHook;\n}\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param name - The name of the exposed remote component. Used to identify the remote component when multiple remote components are exposed on a page.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @param mode - The mode of the Shadow DOM. Defaults to `open`.\n * @param reset - Whether to include a CSS reset style in the shadow DOM. Defaults to `false`.\n * @param children - Loading fallback content to display while the remote component is being fetched.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: RemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n const remoteComponentClient = (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n type={metadata.type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </RemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":"AA8FI;AA9FJ,SAAS,UAAU,gBAAgB;AACnC,SAAS,6BAA6B;AACtC,SAAS,4BAA4B;AAGrC,MAAM,eAAe,QAAQ,IAAI;AAyDjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsD;AACpD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,qBAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,MAAM,SAAS;AAAA,MACf,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,SAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,oBAAC,YAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/next/host/app-router-server.tsx"],"sourcesContent":["import { Children, Suspense } from 'react';\nimport { RemoteComponentClient } from '#internal/next/host/app-router-client';\nimport type { HostConfig } from '#internal/shared/contract/host-config';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface RemoteComponentProps extends HostConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link RemoteComponentProps} (extends {@link HostConfig}).\n *\n * @example\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return <RemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: RemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n const remoteComponentClient = (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n type={metadata.type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </RemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":"AA8DI;AA9DJ,SAAS,UAAU,gBAAgB;AACnC,SAAS,6BAA6B;AAEtC,SAAS,4BAA4B;AAErC,MAAM,eAAe,QAAQ,IAAI;AAyBjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsD;AACpD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,qBAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,MAAM,SAAS;AAAA,MACf,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,SAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,oBAAC,YAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}