@softarc/native-federation-runtime 3.5.0 → 4.0.0-RC1

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 (35) hide show
  1. package/README.md +6 -2
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +320 -0
  5. package/dist/lib/get-shared.d.ts +20 -0
  6. package/dist/lib/get-shared.d.ts.map +1 -0
  7. package/dist/lib/init-federation.d.ts +105 -0
  8. package/dist/lib/init-federation.d.ts.map +1 -0
  9. package/dist/lib/load-remote-module.d.ts +83 -0
  10. package/dist/lib/load-remote-module.d.ts.map +1 -0
  11. package/dist/lib/model/build-notifications-options.d.ts +2 -0
  12. package/dist/lib/model/build-notifications-options.d.ts.map +1 -0
  13. package/dist/lib/model/externals.d.ts +4 -0
  14. package/dist/lib/model/externals.d.ts.map +1 -0
  15. package/dist/lib/model/federation-info.d.ts +7 -0
  16. package/dist/lib/model/federation-info.d.ts.map +1 -0
  17. package/dist/lib/model/global-cache.d.ts +12 -0
  18. package/dist/lib/model/global-cache.d.ts.map +1 -0
  19. package/dist/lib/model/import-map.d.ts +8 -0
  20. package/dist/lib/model/import-map.d.ts.map +1 -0
  21. package/dist/lib/model/remotes.d.ts +10 -0
  22. package/dist/lib/model/remotes.d.ts.map +1 -0
  23. package/dist/lib/utils/add-import-map.d.ts +3 -0
  24. package/dist/lib/utils/add-import-map.d.ts.map +1 -0
  25. package/dist/lib/utils/path-utils.d.ts +14 -0
  26. package/dist/lib/utils/path-utils.d.ts.map +1 -0
  27. package/dist/lib/utils/trusted-types.d.ts +2 -0
  28. package/dist/lib/utils/trusted-types.d.ts.map +1 -0
  29. package/dist/lib/watch-federation-build.d.ts +10 -0
  30. package/dist/lib/watch-federation-build.d.ts.map +1 -0
  31. package/package.json +35 -16
  32. package/LICENSE +0 -8
  33. package/fesm2022/softarc-native-federation-runtime.mjs +0 -568
  34. package/fesm2022/softarc-native-federation-runtime.mjs.map +0 -1
  35. package/index.d.ts +0 -230
package/README.md CHANGED
@@ -1,7 +1,11 @@
1
- # native-federation-runtime
1
+ # runtime
2
2
 
3
3
  This library was generated with [Nx](https://nx.dev).
4
4
 
5
+ ## Building
6
+
7
+ Run `nx build runtime` to build the library.
8
+
5
9
  ## Running unit tests
6
10
 
7
- Run `nx test native-federation-runtime` to execute the unit tests.
11
+ Run `nx test runtime` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,6 @@
1
+ export * from './lib/init-federation.js';
2
+ export * from './lib/load-remote-module.js';
3
+ export * from './lib/model/build-notifications-options.js';
4
+ export * from './lib/model/federation-info.js';
5
+ export * from './lib/model/import-map.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,320 @@
1
+ // packages/runtime/src/lib/model/global-cache.ts
2
+ var nfNamespace = "__NATIVE_FEDERATION__";
3
+ var global = globalThis;
4
+ global[nfNamespace] ??= {
5
+ externals: /* @__PURE__ */ new Map(),
6
+ remoteNamesToRemote: /* @__PURE__ */ new Map(),
7
+ baseUrlToRemoteNames: /* @__PURE__ */ new Map()
8
+ };
9
+ var globalCache = global[nfNamespace];
10
+
11
+ // packages/runtime/src/lib/model/externals.ts
12
+ var externals = globalCache.externals;
13
+ function getExternalKey(shared) {
14
+ return `${shared.packageName}@${shared.version}`;
15
+ }
16
+ function getExternalUrl(shared) {
17
+ const packageKey = getExternalKey(shared);
18
+ return externals.get(packageKey);
19
+ }
20
+ function setExternalUrl(shared, url) {
21
+ const packageKey = getExternalKey(shared);
22
+ externals.set(packageKey, url);
23
+ }
24
+
25
+ // packages/runtime/src/lib/model/import-map.ts
26
+ function mergeImportMaps(map1, map2) {
27
+ return {
28
+ imports: { ...map1.imports, ...map2.imports },
29
+ scopes: { ...map1.scopes, ...map2.scopes }
30
+ };
31
+ }
32
+
33
+ // packages/runtime/src/lib/model/remotes.ts
34
+ var remoteNamesToRemote = globalCache.remoteNamesToRemote;
35
+ var baseUrlToRemoteNames = globalCache.baseUrlToRemoteNames;
36
+ function addRemote(remoteName, remote) {
37
+ remoteNamesToRemote.set(remoteName, remote);
38
+ baseUrlToRemoteNames.set(remote.baseUrl, remoteName);
39
+ }
40
+ function getRemoteNameByBaseUrl(baseUrl) {
41
+ return baseUrlToRemoteNames.get(baseUrl);
42
+ }
43
+ function isRemoteInitialized(baseUrl) {
44
+ return baseUrlToRemoteNames.has(baseUrl);
45
+ }
46
+ function getRemote(remoteName) {
47
+ return remoteNamesToRemote.get(remoteName);
48
+ }
49
+
50
+ // packages/runtime/src/lib/utils/trusted-types.ts
51
+ var global2 = globalThis;
52
+ var policy;
53
+ function createPolicy() {
54
+ if (policy === void 0) {
55
+ policy = null;
56
+ if (global2.trustedTypes) {
57
+ try {
58
+ policy = global2.trustedTypes.createPolicy(
59
+ "native-federation",
60
+ {
61
+ createHTML: (html) => html,
62
+ createScript: (script) => script,
63
+ createScriptURL: (url) => url
64
+ }
65
+ );
66
+ } catch {
67
+ }
68
+ }
69
+ }
70
+ return policy;
71
+ }
72
+ function tryCreateTrustedScript(script) {
73
+ return createPolicy()?.createScript(script) ?? script;
74
+ }
75
+
76
+ // packages/runtime/src/lib/utils/add-import-map.ts
77
+ function appendImportMap(importMap) {
78
+ document.head.appendChild(
79
+ Object.assign(document.createElement("script"), {
80
+ type: tryCreateTrustedScript("importmap-shim"),
81
+ textContent: tryCreateTrustedScript(JSON.stringify(importMap))
82
+ })
83
+ );
84
+ }
85
+
86
+ // packages/runtime/src/lib/utils/path-utils.ts
87
+ function getDirectory(url) {
88
+ const parts = url.split("/");
89
+ parts.pop();
90
+ return parts.join("/");
91
+ }
92
+ function joinPaths(path1, path2) {
93
+ while (path1.endsWith("/")) {
94
+ path1 = path1.substring(0, path1.length - 1);
95
+ }
96
+ if (path2.startsWith("./")) {
97
+ path2 = path2.substring(2, path2.length);
98
+ }
99
+ return `${path1}/${path2}`;
100
+ }
101
+
102
+ // packages/runtime/src/lib/watch-federation-build.ts
103
+ import { BuildNotificationType } from "@softarc/native-federation/domain";
104
+ function watchFederationBuildCompletion(endpoint) {
105
+ const eventSource = new EventSource(endpoint);
106
+ eventSource.onmessage = function(event) {
107
+ const data = JSON.parse(event.data);
108
+ if (data.type === BuildNotificationType.COMPLETED) {
109
+ console.log("[Federation] Rebuild completed, reloading...");
110
+ window.location.reload();
111
+ }
112
+ };
113
+ eventSource.onerror = function(event) {
114
+ console.warn("[Federation] SSE connection error:", event);
115
+ };
116
+ }
117
+
118
+ // packages/runtime/src/lib/init-federation.ts
119
+ async function initFederation(remotesOrManifestUrl = {}, options) {
120
+ const cacheTag = options?.cacheTag ? `?t=${options.cacheTag}` : "";
121
+ const normalizedRemotes = typeof remotesOrManifestUrl === "string" ? await loadManifest(remotesOrManifestUrl + cacheTag) : remotesOrManifestUrl;
122
+ const hostInfo = await loadFederationInfo(`./remoteEntry.json${cacheTag}`);
123
+ const hostImportMap = await processHostInfo(hostInfo);
124
+ const remotesImportMap = await fetchAndRegisterRemotes(normalizedRemotes, {
125
+ throwIfRemoteNotFound: false,
126
+ ...options
127
+ });
128
+ const mergedImportMap = mergeImportMaps(hostImportMap, remotesImportMap);
129
+ appendImportMap(mergedImportMap);
130
+ return mergedImportMap;
131
+ }
132
+ async function loadManifest(manifestUrl) {
133
+ const manifest = await fetch(manifestUrl).then((r) => r.json());
134
+ return manifest;
135
+ }
136
+ function applyCacheTag(url, cacheTag) {
137
+ if (!cacheTag)
138
+ return url;
139
+ const separator = url.includes("?") ? "&" : "?";
140
+ return `${url}${separator}t=${cacheTag}`;
141
+ }
142
+ function handleRemoteLoadError(remoteName, remoteUrl, options, originalError) {
143
+ const errorMessage = `Error loading remote entry for ${remoteName} from file ${remoteUrl}`;
144
+ if (options.throwIfRemoteNotFound) {
145
+ throw new Error(errorMessage);
146
+ }
147
+ console.error(errorMessage);
148
+ console.error(originalError);
149
+ return null;
150
+ }
151
+ async function fetchAndRegisterRemotes(remotes, options = { throwIfRemoteNotFound: false }) {
152
+ const fetchAndRegisterRemotePromises = Object.entries(remotes).map(
153
+ async ([remoteName, remoteUrl]) => {
154
+ try {
155
+ const urlWithCache = applyCacheTag(remoteUrl, options.cacheTag);
156
+ return await fetchAndRegisterRemote(urlWithCache, remoteName);
157
+ } catch (e) {
158
+ return handleRemoteLoadError(remoteName, remoteUrl, options, e);
159
+ }
160
+ }
161
+ );
162
+ const remoteImportMaps = await Promise.all(fetchAndRegisterRemotePromises);
163
+ const importMap = remoteImportMaps.reduce(
164
+ (acc, remoteImportMap) => remoteImportMap ? mergeImportMaps(acc, remoteImportMap) : acc,
165
+ { imports: {}, scopes: {} }
166
+ );
167
+ return importMap;
168
+ }
169
+ async function processRemoteInfos(remotes, options = { throwIfRemoteNotFound: false }) {
170
+ return fetchAndRegisterRemotes(remotes, options);
171
+ }
172
+ async function fetchAndRegisterRemote(federationInfoUrl, remoteName) {
173
+ const baseUrl = getDirectory(federationInfoUrl);
174
+ const remoteInfo = await loadFederationInfo(federationInfoUrl);
175
+ if (!remoteName) {
176
+ remoteName = remoteInfo.name;
177
+ }
178
+ if (remoteInfo.buildNotificationsEndpoint) {
179
+ watchFederationBuildCompletion(baseUrl + remoteInfo.buildNotificationsEndpoint);
180
+ }
181
+ const importMap = createRemoteImportMap(remoteInfo, remoteName, baseUrl);
182
+ addRemote(remoteName, { ...remoteInfo, baseUrl });
183
+ return importMap;
184
+ }
185
+ function createRemoteImportMap(remoteInfo, remoteName, baseUrl) {
186
+ const imports = processExposed(remoteInfo, remoteName, baseUrl);
187
+ const scopes = processRemoteImports(remoteInfo, baseUrl);
188
+ return { imports, scopes };
189
+ }
190
+ async function loadFederationInfo(remoteEntryUrl) {
191
+ const info = await fetch(remoteEntryUrl).then((r) => r.json());
192
+ return info;
193
+ }
194
+ function processRemoteImports(remoteInfo, baseUrl) {
195
+ const scopes = {};
196
+ const scopedImports = {};
197
+ for (const shared of remoteInfo.shared) {
198
+ const outFileName = getExternalUrl(shared) ?? joinPaths(baseUrl, shared.outFileName);
199
+ setExternalUrl(shared, outFileName);
200
+ scopedImports[shared.packageName] = outFileName;
201
+ }
202
+ scopes[baseUrl + "/"] = scopedImports;
203
+ return scopes;
204
+ }
205
+ function processExposed(remoteInfo, remoteName, baseUrl) {
206
+ const imports = {};
207
+ for (const exposed of remoteInfo.exposes) {
208
+ const key = joinPaths(remoteName, exposed.key);
209
+ const value = joinPaths(baseUrl, exposed.outFileName);
210
+ imports[key] = value;
211
+ }
212
+ return imports;
213
+ }
214
+ async function processHostInfo(hostInfo, relBundlesPath = "./") {
215
+ const imports = hostInfo.shared.reduce(
216
+ (acc, cur) => ({
217
+ ...acc,
218
+ [cur.packageName]: relBundlesPath + cur.outFileName
219
+ }),
220
+ {}
221
+ );
222
+ for (const shared of hostInfo.shared) {
223
+ setExternalUrl(shared, relBundlesPath + shared.outFileName);
224
+ }
225
+ return { imports, scopes: {} };
226
+ }
227
+
228
+ // packages/runtime/src/lib/load-remote-module.ts
229
+ async function loadRemoteModule(optionsOrRemoteName, exposedModule) {
230
+ const options = normalizeOptions(optionsOrRemoteName, exposedModule);
231
+ await ensureRemoteInitialized(options);
232
+ const remoteName = getRemoteNameByOptions(options);
233
+ const remote = getRemote(remoteName);
234
+ const fallback = options.fallback;
235
+ const remoteError = !remote ? "unknown remote " + remoteName : "";
236
+ if (!remote && !fallback)
237
+ throw new Error(remoteError);
238
+ if (!remote) {
239
+ logClientError(remoteError);
240
+ return Promise.resolve(fallback);
241
+ }
242
+ const exposedModuleInfo = remote.exposes.find((e) => e.key === options.exposedModule);
243
+ const exposedError = !exposedModuleInfo ? `Unknown exposed module ${options.exposedModule} in remote ${remoteName}` : "";
244
+ if (!exposedModuleInfo && !fallback)
245
+ throw new Error(exposedError);
246
+ if (!exposedModuleInfo) {
247
+ logClientError(exposedError);
248
+ return Promise.resolve(fallback);
249
+ }
250
+ const moduleUrl = joinPaths(remote.baseUrl, exposedModuleInfo.outFileName);
251
+ try {
252
+ const module = _import(moduleUrl);
253
+ return module;
254
+ } catch (e) {
255
+ if (fallback) {
256
+ console.error("error loading remote module", e);
257
+ return fallback;
258
+ }
259
+ throw e;
260
+ }
261
+ }
262
+ function _import(moduleUrl) {
263
+ return typeof importShim !== "undefined" ? importShim(moduleUrl) : import(
264
+ /* @vite-ignore */
265
+ moduleUrl
266
+ );
267
+ }
268
+ function getRemoteNameByOptions(options) {
269
+ let remoteName;
270
+ if (options.remoteName) {
271
+ remoteName = options.remoteName;
272
+ } else if (options.remoteEntry) {
273
+ const baseUrl = getDirectory(options.remoteEntry);
274
+ remoteName = getRemoteNameByBaseUrl(baseUrl);
275
+ } else {
276
+ throw new Error("unexpected arguments: Please pass remoteName or remoteEntry");
277
+ }
278
+ if (!remoteName) {
279
+ throw new Error("unknown remoteName " + remoteName);
280
+ }
281
+ return remoteName;
282
+ }
283
+ async function ensureRemoteInitialized(options) {
284
+ if (options.remoteEntry && !isRemoteInitialized(getDirectory(options.remoteEntry))) {
285
+ const importMap = await fetchAndRegisterRemote(options.remoteEntry);
286
+ appendImportMap(importMap);
287
+ }
288
+ }
289
+ function normalizeOptions(optionsOrRemoteName, exposedModule) {
290
+ let options;
291
+ if (typeof optionsOrRemoteName === "string" && exposedModule) {
292
+ options = {
293
+ remoteName: optionsOrRemoteName,
294
+ exposedModule
295
+ };
296
+ } else if (typeof optionsOrRemoteName === "object" && !exposedModule) {
297
+ options = optionsOrRemoteName;
298
+ } else {
299
+ throw new Error("unexpected arguments: please pass options or a remoteName/exposedModule-pair");
300
+ }
301
+ return options;
302
+ }
303
+ function logClientError(error) {
304
+ if (typeof window !== "undefined") {
305
+ console.error(error);
306
+ }
307
+ }
308
+
309
+ // packages/runtime/src/lib/model/build-notifications-options.ts
310
+ var BUILD_NOTIFICATIONS_ENDPOINT = "/@angular-architects/native-federation:build-notifications";
311
+ export {
312
+ BUILD_NOTIFICATIONS_ENDPOINT,
313
+ fetchAndRegisterRemote,
314
+ fetchAndRegisterRemotes,
315
+ initFederation,
316
+ loadRemoteModule,
317
+ mergeImportMaps,
318
+ processHostInfo,
319
+ processRemoteInfos
320
+ };
@@ -0,0 +1,20 @@
1
+ type Type<T> = new () => T;
2
+ export type ShareObject = {
3
+ version: string;
4
+ scope?: string;
5
+ get: () => Promise<() => Type<unknown>>;
6
+ shareConfig?: {
7
+ singleton?: boolean;
8
+ requiredVersion: string;
9
+ };
10
+ };
11
+ export type ShareConfig = {
12
+ [pkgName: string]: Array<ShareObject>;
13
+ };
14
+ export type ShareOptions = {
15
+ singleton: boolean;
16
+ requiredVersionPrefix: '^' | '~' | '>' | '>=' | '';
17
+ };
18
+ export declare function getShared(options?: ShareOptions): ShareConfig;
19
+ export {};
20
+ //# sourceMappingURL=get-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-shared.d.ts","sourceRoot":"","sources":["../../src/lib/get-shared.ts"],"names":[],"mappings":"AAAA,KAAK,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;AAS3B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE;QACZ,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,qBAAqB,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;CACpD,CAAC;AAOF,wBAAgB,SAAS,CAAC,OAAO,eAAsB,eAyCtD"}
@@ -0,0 +1,105 @@
1
+ import type { FederationInfo } from '@softarc/native-federation/domain';
2
+ import { type InitFederationOptions, type ProcessRemoteInfoOptions } from './model/federation-info.js';
3
+ import { type ImportMap } from './model/import-map.js';
4
+ /**
5
+ * Initializes the Native Federation runtime for the host application.
6
+ *
7
+ * This is the main entry point for setting up federation. It performs the following:
8
+ * 1. Loads the host's remoteEntry.json to discover shared dependencies
9
+ * 2. Loads each remote's remoteEntry.json to discover exposed modules
10
+ * 3. Creates an ES Module import map with proper scoping
11
+ * 4. Injects the import map into the DOM as a <script type="importmap-shim">
12
+ *
13
+ * The import map allows dynamic imports to resolve correctly:
14
+ * - Host shared deps go in root imports (e.g., "angular": "./angular.js")
15
+ * - Remote exposed modules go in root imports (e.g., "mfe1/Component": "http://...")
16
+ * - Remote shared deps go in scoped imports for proper resolution
17
+ *
18
+ * @param remotesOrManifestUrl - Either:
19
+ * - A record of remote names to their remoteEntry.json URLs
20
+ * Example: { mfe1: 'http://localhost:3000/remoteEntry.json' }
21
+ * - A URL to a manifest.json that contains the remotes record
22
+ * Example: 'http://localhost:3000/federation-manifest.json'
23
+ *
24
+ * @param options - Configuration options:
25
+ * - cacheTag: A version string to append as query param for cache busting
26
+ * Example: { cacheTag: 'v1.0.0' } results in '?t=v1.0.0' on all requests
27
+ *
28
+ * @returns The final merged ImportMap that was injected into the DOM
29
+ *
30
+ */
31
+ export declare function initFederation(remotesOrManifestUrl?: Record<string, string> | string, options?: InitFederationOptions): Promise<ImportMap>;
32
+ /**
33
+ * Fetches and registers multiple remote applications in parallel and merges their import maps.
34
+ *
35
+ * This function is the orchestrator for loading all remotes. It:
36
+ * 1. Creates a promise for each remote to load its remoteEntry.json
37
+ * 2. Applies cache busting to each remote URL
38
+ * 3. Handles errors gracefully (logs or throws based on options)
39
+ * 4. Merges all successful remote import maps into one
40
+ *
41
+ * Each remote contributes:
42
+ * - Its exposed modules to the root imports
43
+ * - Its shared dependencies to scoped imports
44
+ *
45
+ * @param remotes - Record of remote names to their remoteEntry.json URLs
46
+ * @param options - Processing options including:
47
+ * - throwIfRemoteNotFound: Whether to throw or log on remote load failure
48
+ * - cacheTag: Cache busting tag to append to URLs
49
+ *
50
+ * @returns Merged import map containing all remotes' contributions
51
+ *
52
+ */
53
+ export declare function fetchAndRegisterRemotes(remotes: Record<string, string>, options?: ProcessRemoteInfoOptions): Promise<ImportMap>;
54
+ /**
55
+ * @deprecated Use `fetchAndRegisterRemotes` instead.
56
+ * @param remotes
57
+ * @param options
58
+ * @returns
59
+ */
60
+ export declare function processRemoteInfos(remotes: Record<string, string>, options?: ProcessRemoteInfoOptions): Promise<ImportMap>;
61
+ /**
62
+ * Fetches a single remote application's remoteEntry.json file and registers it in the system (global registry).
63
+ *
64
+ * This function handles everything needed to integrate one remote:
65
+ * 1. Fetches the remote's remoteEntry.json file
66
+ * 2. Extracts the base URL from the remoteEntry path
67
+ * 3. Creates import map entries for exposed modules and shared deps
68
+ * 4. Registers the remote in the global remotes registry
69
+ * 5. Sets up hot reload watching if configured (development mode)
70
+ *
71
+ * @param federationInfoUrl - Full URL to the remote's remoteEntry.json
72
+ * @param remoteName - Name to use for this remote (optional, uses info.name if not provided)
73
+ *
74
+ * @returns Import map containing this remote's exposed modules and shared dependencies
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const importMap = await fetchAndRegisterRemote(
79
+ * 'http://localhost:3000/mfe1/remoteEntry.json',
80
+ * 'mfe1'
81
+ * );
82
+ * // Result: {
83
+ * // imports: { 'mfe1/Component': 'http://localhost:3000/mfe1/Component.js' },
84
+ * // scopes: { 'http://localhost:3000/mfe1/': { 'lodash': '...' } }
85
+ * // }
86
+ * ```
87
+ */
88
+ export declare function fetchAndRegisterRemote(federationInfoUrl: string, remoteName?: string): Promise<ImportMap>;
89
+ /**
90
+ * Processes the host application's federation info into an import map.
91
+ *
92
+ * The host app typically doesn't expose modules (it's the consumer),
93
+ * but it does share dependencies that should be available to remotes.
94
+ *
95
+ * Host shared dependencies go in root-level imports (not scoped) because:
96
+ * 1. The host loads first and establishes the base environment
97
+ * 2. Remotes should prefer host versions to avoid duplication
98
+ *
99
+ * @param hostInfo - Federation info from the host's remoteEntry.json
100
+ * @param relBundlesPath - Relative path to the host's bundle directory (default: './')
101
+ *
102
+ * @returns Import map with host's shared dependencies in root imports
103
+ */
104
+ export declare function processHostInfo(hostInfo: FederationInfo, relBundlesPath?: string): Promise<ImportMap>;
105
+ //# sourceMappingURL=init-federation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-federation.d.ts","sourceRoot":"","sources":["../../src/lib/init-federation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAExE,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC9B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,SAAS,EAA8C,MAAM,uBAAuB,CAAC;AAMnG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,cAAc,CAClC,oBAAoB,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAW,EAC1D,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,SAAS,CAAC,CA4BpB;AA8CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,GAAE,wBAA2D,GACnE,OAAO,CAAC,SAAS,CAAC,CAuBpB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,GAAE,wBAA2D,GACnE,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,sBAAsB,CAC1C,iBAAiB,EAAE,MAAM,EACzB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,CAAC,CAqBpB;AAqID;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,cAAc,EACxB,cAAc,SAAO,GACpB,OAAO,CAAC,SAAS,CAAC,CAkBpB"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Options for loading a remote module.
3
+ *
4
+ * @template T - The expected type of the module's exports
5
+ *
6
+ * @property remoteEntry - Optional URL to the remote's remoteEntry.json file.
7
+ * Used for lazy-loading remotes that weren't registered during initFederation
8
+ * Example: 'http://localhost:3000/remoteEntry.json'
9
+ *
10
+ * @property remoteName - Optional name of the remote application.
11
+ * Should match the name used during initFederation or the name in remoteEntry.json.
12
+ * Example: 'mfe1'
13
+ *
14
+ * @property exposedModule - The key of the exposed module to load (required).
15
+ * Must match the key defined in the remote's federation config.
16
+ * Example: './Component' or './Dashboard'
17
+ *
18
+ * @property fallback - Optional fallback value to return if the remote or module cannot be loaded.
19
+ * Prevents throwing errors and provides graceful degradation.
20
+ * Example: A default component or null
21
+ */
22
+ export type LoadRemoteModuleOptions<T = any> = {
23
+ remoteEntry?: string;
24
+ remoteName?: string;
25
+ exposedModule: string;
26
+ fallback?: T;
27
+ };
28
+ /**
29
+ * Dynamically loads a remote module at runtime from a federated application.
30
+ *
31
+ * This is the primary API for consuming remote modules after federation has been initialized.
32
+ * It supports two calling patterns:
33
+ *
34
+ * **Pattern 1: Using options object**
35
+ * ```typescript
36
+ * const module = await loadRemoteModule({
37
+ * remoteName: 'mfe1',
38
+ * exposedModule: './Component',
39
+ * fallback: DefaultComponent
40
+ * });
41
+ * ```
42
+ *
43
+ * **Pattern 2: Using positional arguments**
44
+ * ```typescript
45
+ * const module = await loadRemoteModule('mfe1', './Component');
46
+ * ```
47
+ *
48
+ * ## Loading Process
49
+ *
50
+ * 1. **Normalize Options**: Converts arguments into a standard options object
51
+ * 2. **Ensure Remote Initialized**: If remoteEntry is provided and remote isn't loaded,
52
+ * fetches and registers it dynamically
53
+ * 3. **Resolve Remote Name**: Determines remote name from options or remoteEntry URL
54
+ * 4. **Validate Remote**: Checks if remote exists in the registry
55
+ * 5. **Validate Exposed Module**: Verifies the requested module is exposed by the remote
56
+ * 6. **Import Module**: Uses dynamic import or import-shim to load the module
57
+ * 7. **Handle Errors**: Returns fallback if provided, otherwise throws
58
+ *
59
+ * ## Lazy Loading Support
60
+ *
61
+ * If you provide a `remoteEntry` URL for a remote that wasn't initialized during
62
+ * `initFederation()`, this function will automatically:
63
+ * - Fetch the remote's remoteEntry.json
64
+ * - Register it in the global registry
65
+ * - Update the import map
66
+ * - Then load the requested module
67
+ *
68
+ * This enables on-demand loading of remotes based on user interactions.
69
+ *
70
+ *
71
+ * @template T - The expected type of the module's exports
72
+ *
73
+ * @param options - Configuration object for loading the remote module
74
+ * @returns Promise resolving to the loaded module or fallback value
75
+ *
76
+ * @throws Error if remote is not found and no fallback is provided
77
+ * @throws Error if exposed module doesn't exist and no fallback is provided
78
+ * @throws Error if module import fails and no fallback is provided
79
+ *
80
+ */
81
+ export declare function loadRemoteModule<T = any>(options: LoadRemoteModuleOptions): Promise<T>;
82
+ export declare function loadRemoteModule<T = any>(remoteName: string, exposedModule: string): Promise<T>;
83
+ //# sourceMappingURL=load-remote-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-remote-module.d.ts","sourceRoot":"","sources":["../../src/lib/load-remote-module.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,uBAAuB,CAAC,CAAC,GAAG,GAAG,IAAI;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAC9F,wBAAsB,gBAAgB,CAAC,CAAC,GAAG,GAAG,EAC5C,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const BUILD_NOTIFICATIONS_ENDPOINT = "/@angular-architects/native-federation:build-notifications";
2
+ //# sourceMappingURL=build-notifications-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-notifications-options.d.ts","sourceRoot":"","sources":["../../../src/lib/model/build-notifications-options.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,+DACqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SharedInfo } from '@softarc/native-federation/domain';
2
+ export declare function getExternalUrl(shared: SharedInfo): string | undefined;
3
+ export declare function setExternalUrl(shared: SharedInfo, url: string): void;
4
+ //# sourceMappingURL=externals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"externals.d.ts","sourceRoot":"","sources":["../../../src/lib/model/externals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AASpE,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAGrE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAGpE"}
@@ -0,0 +1,7 @@
1
+ export interface InitFederationOptions {
2
+ cacheTag?: string;
3
+ }
4
+ export interface ProcessRemoteInfoOptions extends InitFederationOptions {
5
+ throwIfRemoteNotFound: boolean;
6
+ }
7
+ //# sourceMappingURL=federation-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-info.d.ts","sourceRoot":"","sources":["../../../src/lib/model/federation-info.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAyB,SAAQ,qBAAqB;IACrE,qBAAqB,EAAE,OAAO,CAAC;CAChC"}
@@ -0,0 +1,12 @@
1
+ import type { Remote } from './remotes.js';
2
+ export declare const nfNamespace = "__NATIVE_FEDERATION__";
3
+ export type NfCache = {
4
+ externals: Map<string, string>;
5
+ remoteNamesToRemote: Map<string, Remote>;
6
+ baseUrlToRemoteNames: Map<string, string>;
7
+ };
8
+ export type Global = {
9
+ [nfNamespace]: NfCache;
10
+ };
11
+ export declare const globalCache: NfCache;
12
+ //# sourceMappingURL=global-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-cache.d.ts","sourceRoot":"","sources":["../../../src/lib/model/global-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,eAAO,MAAM,WAAW,0BAA0B,CAAC;AAEnD,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAUF,eAAO,MAAM,WAAW,SAAsB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type Imports = Record<string, string>;
2
+ export type Scopes = Record<string, Imports>;
3
+ export type ImportMap = {
4
+ imports: Imports;
5
+ scopes: Scopes;
6
+ };
7
+ export declare function mergeImportMaps(map1: ImportMap, map2: ImportMap): ImportMap;
8
+ //# sourceMappingURL=import-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-map.d.ts","sourceRoot":"","sources":["../../../src/lib/model/import-map.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE7C,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,SAAS,CAK3E"}
@@ -0,0 +1,10 @@
1
+ import type { FederationInfo } from '@softarc/native-federation/domain';
2
+ export type Remote = FederationInfo & {
3
+ baseUrl: string;
4
+ };
5
+ export declare function addRemote(remoteName: string, remote: Remote): void;
6
+ export declare function getRemoteNameByBaseUrl(baseUrl: string): string | undefined;
7
+ export declare function isRemoteInitialized(baseUrl: string): boolean;
8
+ export declare function getRemote(remoteName: string): Remote | undefined;
9
+ export declare function hasRemote(remoteName: string): boolean;
10
+ //# sourceMappingURL=remotes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remotes.d.ts","sourceRoot":"","sources":["../../../src/lib/model/remotes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGxE,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAKF,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGlE;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAErD"}
@@ -0,0 +1,3 @@
1
+ import type { ImportMap } from '../model/import-map.js';
2
+ export declare function appendImportMap(importMap: ImportMap): void;
3
+ //# sourceMappingURL=add-import-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-import-map.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/add-import-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,QAOnD"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Returns the full directory of a given path.
3
+ * @param url - The path to get the directory of.
4
+ * @returns The full directory of the path.
5
+ */
6
+ export declare function getDirectory(url: string): string;
7
+ /**
8
+ * Joins two paths together taking into account trailing slashes and "./" prefixes.
9
+ * @param path1 - The first path to join.
10
+ * @param path2 - The second path to join.
11
+ * @returns The joined path.
12
+ */
13
+ export declare function joinPaths(path1: string, path2: string): string;
14
+ //# sourceMappingURL=path-utils.d.ts.map