@mikkel-ol/federation-session 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -0
  3. package/builders.json +15 -0
  4. package/collection.json +10 -0
  5. package/dist/host/gateway.d.ts +17 -0
  6. package/dist/host/gateway.d.ts.map +1 -0
  7. package/dist/host/gateway.js +333 -0
  8. package/dist/host/gateway.js.map +1 -0
  9. package/dist/host/index.d.ts +4 -0
  10. package/dist/host/index.d.ts.map +1 -0
  11. package/dist/host/index.js +51 -0
  12. package/dist/host/index.js.map +1 -0
  13. package/dist/host/runtime-browser.js +191 -0
  14. package/dist/host/runtime.d.ts +2 -0
  15. package/dist/host/runtime.d.ts.map +1 -0
  16. package/dist/host/runtime.js +14 -0
  17. package/dist/host/runtime.js.map +1 -0
  18. package/dist/host/schema.json +36 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +11 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/remote/index.d.ts +4 -0
  24. package/dist/remote/index.d.ts.map +1 -0
  25. package/dist/remote/index.js +318 -0
  26. package/dist/remote/index.js.map +1 -0
  27. package/dist/remote/schema.json +22 -0
  28. package/dist/setup/index.d.ts +14 -0
  29. package/dist/setup/index.d.ts.map +1 -0
  30. package/dist/setup/index.js +395 -0
  31. package/dist/setup/index.js.map +1 -0
  32. package/dist/setup/schema.json +63 -0
  33. package/dist/shared/architect.d.ts +7 -0
  34. package/dist/shared/architect.d.ts.map +1 -0
  35. package/dist/shared/architect.js +104 -0
  36. package/dist/shared/architect.js.map +1 -0
  37. package/dist/shared/schema.d.ts +15 -0
  38. package/dist/shared/schema.d.ts.map +1 -0
  39. package/dist/shared/schema.js +3 -0
  40. package/dist/shared/schema.js.map +1 -0
  41. package/package.json +61 -0
@@ -0,0 +1,191 @@
1
+ // src/host/runtime-browser.ts
2
+ var pageUrl = new URL(location.href);
3
+ var hashParams = new URLSearchParams(pageUrl.hash.slice(1));
4
+ var token = pageUrl.searchParams.get("join") ?? hashParams.get("join");
5
+ if (token) {
6
+ pageUrl.searchParams.delete("join");
7
+ hashParams.delete("join");
8
+ pageUrl.hash = hashParams.size ? `#${hashParams}` : "";
9
+ history.replaceState(
10
+ null,
11
+ "",
12
+ `${pageUrl.pathname}${pageUrl.search}${pageUrl.hash}`
13
+ );
14
+ }
15
+ await waitForHostBootstrap();
16
+ var [{ createApplication }, { createComponent }] = await Promise.all([
17
+ import("@angular/platform-browser"),
18
+ import("@angular/core")
19
+ ]);
20
+ var state = /* @__PURE__ */ new Map();
21
+ var app = await createApplication({ providers: [] });
22
+ var panelEnabled = new URL(import.meta.url).searchParams.get("panel") !== "false";
23
+ var stage = document.querySelector("federation-session-stage") ?? createDefaultStage();
24
+ var panel = panelEnabled ? createPanel() : { update: (_session) => void 0 };
25
+ async function refresh() {
26
+ const response = await fetch("/__federation_session/state", { cache: "no-store" });
27
+ if (!response.ok) return;
28
+ const session = await response.json();
29
+ panel.update(session);
30
+ for (const remote of session.remotes) {
31
+ let item = state.get(remote.name);
32
+ if (!item) {
33
+ item = createSlot(remote);
34
+ state.set(remote.name, item);
35
+ stage.append(item.slot);
36
+ }
37
+ item.status.textContent = remote.status;
38
+ item.slot.dataset.status = remote.status;
39
+ if (remote.remoteEntry && item.revision !== remote.revision) {
40
+ await mountRevision(item, remote);
41
+ }
42
+ }
43
+ for (const [name, item] of state) {
44
+ if (!session.remotes.some((remote) => remote.name === name)) {
45
+ item.componentRef?.destroy();
46
+ item.slot.remove();
47
+ state.delete(name);
48
+ }
49
+ }
50
+ }
51
+ function createDefaultStage() {
52
+ const element = document.createElement("federation-session-stage");
53
+ element.dataset.default = "true";
54
+ document.body.append(element);
55
+ return element;
56
+ }
57
+ function createSlot(remote) {
58
+ const slot = document.createElement("section");
59
+ slot.className = "federation-session-slot";
60
+ const header = document.createElement("header");
61
+ const name = document.createElement("strong");
62
+ name.textContent = remote.name;
63
+ const status = document.createElement("span");
64
+ header.append(name, status);
65
+ const elementName = `federation-remote-${remote.name}`;
66
+ if (!customElements.get(elementName)) {
67
+ customElements.define(elementName, class extends HTMLElement {
68
+ });
69
+ }
70
+ const element = document.createElement(elementName);
71
+ slot.append(header, element);
72
+ return { slot, element, status, revision: 0 };
73
+ }
74
+ async function mountRevision(item, remote) {
75
+ try {
76
+ const entry = new URL(remote.remoteEntry);
77
+ entry.searchParams.set("revision", String(remote.revision));
78
+ const response = await fetch(entry);
79
+ if (!response.ok) {
80
+ throw new Error(`Remote entry returned ${response.status}`);
81
+ }
82
+ const manifest = await response.json();
83
+ const exposure = manifest.exposes?.find(
84
+ (candidate) => candidate.key === "./Component"
85
+ );
86
+ if (!exposure?.outFileName) {
87
+ throw new Error("Remote entry does not expose ./Component");
88
+ }
89
+ const componentUrl = new URL(exposure.outFileName, entry);
90
+ componentUrl.searchParams.set("revision", String(remote.revision));
91
+ const module = await importShim(componentUrl.href);
92
+ const component = module.AppComponent ?? module.default;
93
+ if (!component) {
94
+ throw new Error("./Component does not export AppComponent or default");
95
+ }
96
+ const next = document.createElement("div");
97
+ const componentRef = createComponent(component, {
98
+ environmentInjector: app.injector,
99
+ hostElement: next
100
+ });
101
+ app.attachView(componentRef.hostView);
102
+ item.element.replaceChildren(next);
103
+ item.componentRef?.destroy();
104
+ item.componentRef = componentRef;
105
+ item.revision = remote.revision;
106
+ item.status.textContent = "connected";
107
+ } catch (error) {
108
+ item.status.textContent = item.revision ? "last revision active" : "not ready";
109
+ console.error("Failed to load remote", remote.name, error);
110
+ }
111
+ }
112
+ function createPanel() {
113
+ const root = document.createElement("aside");
114
+ root.className = "federation-session-panel";
115
+ const toggle = document.createElement("button");
116
+ toggle.type = "button";
117
+ toggle.textContent = "Session";
118
+ const panel2 = document.createElement("div");
119
+ panel2.hidden = true;
120
+ const invite = document.createElement("code");
121
+ const qr = document.createElement("img");
122
+ const list = document.createElement("div");
123
+ panel2.append(invite, qr, list);
124
+ root.append(toggle, panel2);
125
+ document.body.append(root);
126
+ toggle.addEventListener("click", () => {
127
+ panel2.hidden = !panel2.hidden;
128
+ });
129
+ let qrLoaded = false;
130
+ return {
131
+ async update(session) {
132
+ const fullInvite = token ? `${session.publicUrl}?join=${encodeURIComponent(token)}` : session.publicUrl;
133
+ invite.textContent = fullInvite;
134
+ if (token && !qrLoaded) {
135
+ qrLoaded = true;
136
+ const response = await fetch("/__federation_session/invite-qr", {
137
+ headers: { Authorization: `Bearer ${token}` }
138
+ });
139
+ if (response.ok) qr.src = URL.createObjectURL(await response.blob());
140
+ }
141
+ list.replaceChildren(
142
+ ...session.remotes.map((remote) => {
143
+ const row = document.createElement("div");
144
+ const label = document.createElement("span");
145
+ label.textContent = `${remote.name} - ${remote.status}`;
146
+ row.append(label);
147
+ if (token) {
148
+ const remove = document.createElement("button");
149
+ remove.type = "button";
150
+ remove.textContent = "Remove";
151
+ remove.addEventListener("click", () => {
152
+ void fetch(
153
+ `/__federation_session/remotes/${encodeURIComponent(remote.name)}`,
154
+ {
155
+ method: "DELETE",
156
+ headers: { Authorization: `Bearer ${token}` }
157
+ }
158
+ );
159
+ });
160
+ row.append(remove);
161
+ }
162
+ return row;
163
+ })
164
+ );
165
+ }
166
+ };
167
+ }
168
+ var style = document.createElement("style");
169
+ style.textContent = `
170
+ federation-session-stage[data-default="true"] { display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;padding:12px;min-height:60vh }
171
+ .federation-session-slot { min-width:0;border:1px solid #c9ced6;background:#fff }
172
+ .federation-session-slot>header { display:flex;justify-content:space-between;padding:6px 10px;background:#f2f4f7;font:13px system-ui }
173
+ .federation-session-slot[data-status="reconnecting"] { opacity:.72 }
174
+ .federation-session-slot> :not(header) { display:block;padding:12px }
175
+ .federation-session-panel { position:fixed;right:12px;bottom:12px;z-index:2147483647;font:13px system-ui;color:#17191c }
176
+ .federation-session-panel>button { float:right }
177
+ .federation-session-panel>div { clear:both;width:min(360px,calc(100vw - 24px));max-height:70vh;overflow:auto;background:#fff;border:1px solid #aeb4bd;padding:12px;box-shadow:0 8px 30px #0002 }
178
+ .federation-session-panel code { display:block;overflow-wrap:anywhere;margin-bottom:8px }
179
+ .federation-session-panel img { display:block;width:180px;height:180px;margin:0 auto 8px }
180
+ .federation-session-panel div div { display:flex;justify-content:space-between;gap:8px;padding:4px 0 }
181
+ `;
182
+ document.head.append(style);
183
+ async function waitForHostBootstrap() {
184
+ const deadline = Date.now() + 1e4;
185
+ while (Date.now() < deadline) {
186
+ if (document.querySelector("app-root")?.childNodes.length) return;
187
+ await new Promise((resolve) => setTimeout(resolve, 25));
188
+ }
189
+ }
190
+ await refresh();
191
+ setInterval(() => void refresh(), 1e3);
@@ -0,0 +1,2 @@
1
+ export declare function runtimeSource(): string;
2
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/host/runtime.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,IAAI,MAAM,CAGtC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runtimeSource = runtimeSource;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ let source;
10
+ function runtimeSource() {
11
+ source ??= (0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, "runtime-browser.js"), "utf8");
12
+ return source;
13
+ }
14
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/host/runtime.ts"],"names":[],"mappings":";;;;;AAKA,sCAGC;AARD,qCAAuC;AACvC,0DAA6B;AAE7B,IAAI,MAA0B,CAAC;AAE/B,SAAgB,aAAa;IAC3B,MAAM,KAAK,IAAA,sBAAY,EAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "title": "Federation Session Host",
4
+ "type": "object",
5
+ "properties": {
6
+ "target": {
7
+ "type": "string",
8
+ "description": "Native Federation dev-server target"
9
+ },
10
+ "yatsiServerUrl": {
11
+ "type": "string",
12
+ "description": "YATSI server URL including http or https"
13
+ },
14
+ "capacity": {
15
+ "type": "number",
16
+ "minimum": 1,
17
+ "default": 24
18
+ },
19
+ "gatewayPort": {
20
+ "type": "number",
21
+ "minimum": 0,
22
+ "default": 0
23
+ },
24
+ "open": {
25
+ "type": "boolean",
26
+ "default": false
27
+ },
28
+ "panel": {
29
+ "type": "boolean",
30
+ "default": true,
31
+ "description": "Show the session panel in the host browser"
32
+ }
33
+ },
34
+ "required": ["target", "yatsiServerUrl"],
35
+ "additionalProperties": false
36
+ }
@@ -0,0 +1,3 @@
1
+ export { default as hostBuilder } from "./host/index";
2
+ export { default as remoteBuilder } from "./remote/index";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.remoteBuilder = exports.hostBuilder = void 0;
7
+ var index_1 = require("./host/index");
8
+ Object.defineProperty(exports, "hostBuilder", { enumerable: true, get: function () { return __importDefault(index_1).default; } });
9
+ var index_2 = require("./remote/index");
10
+ Object.defineProperty(exports, "remoteBuilder", { enumerable: true, get: function () { return __importDefault(index_2).default; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,sCAAsD;AAA7C,qHAAA,OAAO,OAAe;AAC/B,wCAA0D;AAAjD,uHAAA,OAAO,OAAiB"}
@@ -0,0 +1,4 @@
1
+ import type { RemoteSchema } from "../shared/schema";
2
+ declare const _default: import("@angular-devkit/architect").Builder<RemoteSchema & import("@angular-devkit/core").JsonObject>;
3
+ export default _default;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/remote/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;;AASrD,wBA6LG"}
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const architect_1 = require("@angular-devkit/architect");
4
+ const yatsi_1 = require("@mikkel-ol/yatsi");
5
+ const architect_2 = require("../shared/architect");
6
+ const MAX_REMOTE_ENTRY_BYTES = 1024 * 1024;
7
+ exports.default = (0, architect_1.createBuilder)((options, context) => {
8
+ let run;
9
+ let completeSuccessfully;
10
+ let activeTunnel;
11
+ let registrationToken;
12
+ const remoteName = validateRemoteName(options.remoteName);
13
+ let remoteEntry = "";
14
+ let closing = false;
15
+ let initialized = false;
16
+ let initializing;
17
+ let publicationQueue = Promise.resolve();
18
+ const sessionUrl = new URL(options.sessionUrl);
19
+ const joinToken = requiredJoinToken(sessionUrl);
20
+ sessionUrl.search = "";
21
+ sessionUrl.hash = "";
22
+ const cleanup = async () => {
23
+ if (closing)
24
+ return;
25
+ closing = true;
26
+ activeTunnel?.close();
27
+ if (registrationToken) {
28
+ await controlRequest(sessionUrl, "/__federation_session/registration", registrationToken, {
29
+ method: "DELETE",
30
+ }).catch(() => undefined);
31
+ }
32
+ };
33
+ context.addTeardown(cleanup);
34
+ return (0, architect_2.delegateBuilder)(options.target, context, async () => {
35
+ if (!initialized)
36
+ return;
37
+ publicationQueue = publicationQueue.then(async () => {
38
+ if (!registrationToken || !remoteEntry)
39
+ return;
40
+ try {
41
+ await publishReadyRevision(sessionUrl, registrationToken, remoteEntry);
42
+ context.logger.info(`${remoteName} published from ${remoteEntry}`);
43
+ }
44
+ catch (error) {
45
+ context.logger.error(`Remote revision was not published: ${error instanceof Error ? error.message : String(error)}`);
46
+ }
47
+ });
48
+ await publicationQueue;
49
+ }, (scheduled, complete) => {
50
+ run = scheduled;
51
+ completeSuccessfully = complete;
52
+ initializing ??= initialize();
53
+ void initializing.catch(async (error) => {
54
+ context.logger.error(error instanceof Error ? error.message : String(error));
55
+ await run?.stop();
56
+ });
57
+ });
58
+ async function initialize() {
59
+ context.logger.info("Waiting for the remote Native Federation server");
60
+ const port = await (0, architect_2.resolveDevServerPort)(options.target, context);
61
+ await (0, architect_2.waitForDevServer)(port, "/remoteEntry.json");
62
+ context.logger.info("Remote server ready; registering with the federation session");
63
+ const registration = await controlRequest(sessionUrl, "/__federation_session/register", joinToken, {
64
+ method: "POST",
65
+ body: JSON.stringify({ name: remoteName }),
66
+ });
67
+ registrationToken = registration.registrationToken;
68
+ activeTunnel = await openGrantedTunnel(registration.grant, port, sessionUrl);
69
+ remoteEntry = `${activeTunnel.url}/remoteEntry.json`;
70
+ watchTunnel(activeTunnel);
71
+ void watchSessionEvents();
72
+ await publishReadyRevision(sessionUrl, registrationToken, remoteEntry);
73
+ initialized = true;
74
+ context.logger.info(`${remoteName} published from ${remoteEntry}`);
75
+ void watchFederationBuilds(port);
76
+ }
77
+ async function watchFederationBuilds(port) {
78
+ while (!closing) {
79
+ try {
80
+ const response = await fetch(`http://localhost:${port}/@angular-architects/native-federation:build-notifications`);
81
+ if (!response.ok || !response.body)
82
+ throw new Error("Build notification stream unavailable");
83
+ for await (const event of readSse(response.body)) {
84
+ if (event.type !== "federation-rebuild-complete" || !registrationToken || !remoteEntry) {
85
+ continue;
86
+ }
87
+ try {
88
+ await publishReadyRevision(sessionUrl, registrationToken, remoteEntry);
89
+ context.logger.info(`${remoteName} revision published`);
90
+ }
91
+ catch (error) {
92
+ context.logger.error(`Remote revision was not published: ${error instanceof Error ? error.message : String(error)}`);
93
+ }
94
+ }
95
+ }
96
+ catch {
97
+ if (!closing)
98
+ await sleep(500);
99
+ }
100
+ }
101
+ }
102
+ function watchTunnel(current) {
103
+ void current.closed.then(async () => {
104
+ if (closing || activeTunnel !== current || !registrationToken)
105
+ return;
106
+ const deadline = Date.now() + 30_000;
107
+ let delay = 250;
108
+ while (!closing && Date.now() < deadline) {
109
+ try {
110
+ const response = await controlRequest(sessionUrl, "/__federation_session/grant", registrationToken, { method: "POST" });
111
+ const replacement = await openGrantedTunnel(response.grant, await (0, architect_2.resolveDevServerPort)(options.target, context), sessionUrl);
112
+ activeTunnel = replacement;
113
+ remoteEntry = `${replacement.url}/remoteEntry.json`;
114
+ watchTunnel(replacement);
115
+ await publishReadyRevision(sessionUrl, registrationToken, remoteEntry);
116
+ context.logger.info(`${remoteName} tunnel recovered`);
117
+ return;
118
+ }
119
+ catch {
120
+ await sleep(delay);
121
+ delay = Math.min(delay * 2, 4_000);
122
+ }
123
+ }
124
+ context.logger.error("Remote tunnel could not reconnect within 30 seconds");
125
+ await run?.stop();
126
+ });
127
+ }
128
+ async function watchSessionEvents() {
129
+ if (!registrationToken)
130
+ return;
131
+ const deadline = () => Date.now() + 30_000;
132
+ let unavailableUntil = deadline();
133
+ let delay = 250;
134
+ while (!closing) {
135
+ try {
136
+ const response = await fetch(new URL("/__federation_session/events", sessionUrl), {
137
+ headers: { Authorization: `Bearer ${registrationToken}` },
138
+ });
139
+ if (!response.ok || !response.body)
140
+ throw new Error("Federation session event stream unavailable");
141
+ unavailableUntil = deadline();
142
+ delay = 250;
143
+ for await (const event of readSse(response.body)) {
144
+ if (event.type === "session-ended" || event.type === "removed") {
145
+ closing = true;
146
+ context.logger.info(event.type === "session-ended" ? "Federation session ended" : "Remote removed by host");
147
+ activeTunnel?.close();
148
+ completeSuccessfully?.();
149
+ return;
150
+ }
151
+ }
152
+ if (!(await hostSessionExists(sessionUrl))) {
153
+ closing = true;
154
+ context.logger.info("Federation session ended");
155
+ activeTunnel?.close();
156
+ completeSuccessfully?.();
157
+ return;
158
+ }
159
+ }
160
+ catch {
161
+ if (Date.now() >= unavailableUntil) {
162
+ context.logger.error("Federation session unavailable for 30 seconds");
163
+ await run?.stop();
164
+ return;
165
+ }
166
+ await sleep(delay);
167
+ delay = Math.min(delay * 2, 4_000);
168
+ }
169
+ }
170
+ }
171
+ });
172
+ async function hostSessionExists(sessionUrl) {
173
+ try {
174
+ const response = await fetch(new URL("/__federation_session/session", sessionUrl), {
175
+ redirect: "manual",
176
+ });
177
+ return response.ok;
178
+ }
179
+ catch {
180
+ return true;
181
+ }
182
+ }
183
+ async function openGrantedTunnel(grant, port, sessionUrl) {
184
+ const serverHost = yatsiServerHost(sessionUrl);
185
+ return yatsi_1.tunnel.start({
186
+ port,
187
+ token: grant.token,
188
+ domain: serverHost,
189
+ secure: sessionUrl.protocol === "https:",
190
+ });
191
+ }
192
+ function yatsiServerHost(sessionUrl) {
193
+ const labels = sessionUrl.hostname.split(".");
194
+ if (labels.length < 2)
195
+ throw new Error("Federation Session URL does not contain a YATSI subdomain");
196
+ labels.shift();
197
+ return `${labels.join(".")}${sessionUrl.port ? `:${sessionUrl.port}` : ""}`;
198
+ }
199
+ async function publishReadyRevision(sessionUrl, token, remoteEntry) {
200
+ const deadline = Date.now() + 10_000;
201
+ let delay = 100;
202
+ let lastError;
203
+ while (Date.now() < deadline) {
204
+ try {
205
+ await fetchRemoteEntry(remoteEntry);
206
+ return await controlRequest(sessionUrl, "/__federation_session/revision", token, {
207
+ method: "POST",
208
+ body: JSON.stringify({ remoteEntry }),
209
+ });
210
+ }
211
+ catch (error) {
212
+ lastError = error;
213
+ await sleep(delay);
214
+ delay = Math.min(delay * 2, 1_000);
215
+ }
216
+ }
217
+ throw lastError instanceof Error ? lastError : new Error("Remote entry did not become ready");
218
+ }
219
+ async function fetchRemoteEntry(remoteEntry) {
220
+ const controller = new AbortController();
221
+ const timeout = setTimeout(() => controller.abort(), 5_000);
222
+ try {
223
+ const response = await fetch(remoteEntry, {
224
+ redirect: "manual",
225
+ signal: controller.signal,
226
+ });
227
+ if (!response.ok)
228
+ throw new Error(`Remote entry returned ${response.status}`);
229
+ if (response.status >= 300 && response.status < 400) {
230
+ throw new Error("Remote entry redirects are not allowed");
231
+ }
232
+ if (!response.headers.get("content-type")?.includes("application/json")) {
233
+ throw new Error("Remote entry must be JSON");
234
+ }
235
+ const contentLength = Number(response.headers.get("content-length") || 0);
236
+ if (contentLength > MAX_REMOTE_ENTRY_BYTES) {
237
+ throw new Error("Remote entry is too large");
238
+ }
239
+ const body = await readLimitedBody(response, MAX_REMOTE_ENTRY_BYTES);
240
+ JSON.parse(body);
241
+ }
242
+ finally {
243
+ clearTimeout(timeout);
244
+ }
245
+ }
246
+ async function readLimitedBody(response, limit) {
247
+ if (!response.body)
248
+ return "";
249
+ const reader = response.body.getReader();
250
+ const decoder = new TextDecoder();
251
+ let body = "";
252
+ let size = 0;
253
+ while (true) {
254
+ const { done, value } = await reader.read();
255
+ if (done)
256
+ break;
257
+ size += value.byteLength;
258
+ if (size > limit) {
259
+ await reader.cancel();
260
+ throw new Error("Remote entry is too large");
261
+ }
262
+ body += decoder.decode(value, { stream: true });
263
+ }
264
+ return body + decoder.decode();
265
+ }
266
+ async function controlRequest(sessionUrl, pathName, token, init) {
267
+ const response = await fetch(new URL(pathName, sessionUrl), {
268
+ ...init,
269
+ headers: {
270
+ Authorization: `Bearer ${token}`,
271
+ "Content-Type": "application/json",
272
+ ...init.headers,
273
+ },
274
+ });
275
+ const body = (await response.json().catch(() => ({})));
276
+ if (!response.ok)
277
+ throw new Error(body.error || `Federation session request failed with ${response.status}`);
278
+ return body;
279
+ }
280
+ async function* readSse(stream) {
281
+ const reader = stream.getReader();
282
+ const decoder = new TextDecoder();
283
+ let buffer = "";
284
+ while (true) {
285
+ const { done, value } = await reader.read();
286
+ if (done)
287
+ return;
288
+ buffer += decoder.decode(value, { stream: true });
289
+ let boundary;
290
+ while ((boundary = buffer.indexOf("\n\n")) >= 0) {
291
+ const frame = buffer.slice(0, boundary);
292
+ buffer = buffer.slice(boundary + 2);
293
+ const data = frame
294
+ .split("\n")
295
+ .filter((line) => line.startsWith("data:"))
296
+ .map((line) => line.slice(5).trim())
297
+ .join("\n");
298
+ if (data)
299
+ yield JSON.parse(data);
300
+ }
301
+ }
302
+ }
303
+ function sleep(ms) {
304
+ return new Promise((resolve) => setTimeout(resolve, ms));
305
+ }
306
+ function requiredJoinToken(url) {
307
+ const token = url.searchParams.get("join");
308
+ if (!token)
309
+ throw new Error("Federation Session URL must contain a join token");
310
+ return token;
311
+ }
312
+ function validateRemoteName(name) {
313
+ if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(name)) {
314
+ throw new Error("remoteName must be lowercase kebab-case");
315
+ }
316
+ return name;
317
+ }
318
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/remote/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "title": "Federation Session Remote",
4
+ "type": "object",
5
+ "properties": {
6
+ "target": {
7
+ "type": "string",
8
+ "description": "Native Federation dev-server target"
9
+ },
10
+ "sessionUrl": {
11
+ "type": "string",
12
+ "description": "Federation Session URL provided by the host"
13
+ },
14
+ "remoteName": {
15
+ "type": "string",
16
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
17
+ "description": "Lowercase kebab-case Native Federation remote name"
18
+ }
19
+ },
20
+ "required": ["target", "remoteName", "sessionUrl"],
21
+ "additionalProperties": false
22
+ }
@@ -0,0 +1,14 @@
1
+ import { type Rule } from "@angular-devkit/schematics";
2
+ interface SetupOptions {
3
+ project: string;
4
+ role: "host" | "remote";
5
+ yatsiServerUrl?: string;
6
+ remoteName?: string;
7
+ component?: string;
8
+ port?: number;
9
+ capacity?: number;
10
+ skipInstall?: boolean;
11
+ }
12
+ export default function setup(options: SetupOptions): Rule;
13
+ export {};
14
+ //# sourceMappingURL=index.d.ts.map