@mfe-orchestrator-hub/client 0.2.1 → 0.3.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.
package/README.md CHANGED
@@ -78,11 +78,14 @@ When the user only appears later, or changes without a reload, use [`setUserId()
78
78
 
79
79
  ## Bundler configuration
80
80
 
81
- The string below is injected into the host bundle, so the bare specifier is resolved by the host's
82
- own bundler. This is exactly the form the console generates.
81
+ These are exactly the forms the console generates. The two bundlers need different ones, because they
82
+ do different things with the string.
83
83
 
84
84
  ### Vite — `@originjs/vite-plugin-federation`
85
85
 
86
+ The plugin compiles the `external` expression into the host bundle, so the bare specifier is resolved
87
+ by the host's own bundler and the expression only has to resolve to the URL.
88
+
86
89
  ```js
87
90
  federation({
88
91
  name: "shell",
@@ -102,12 +105,28 @@ federation({
102
105
  new ModuleFederationPlugin({
103
106
  name: "shell",
104
107
  remotes: {
105
- checkoutnew: `promise import('@mfe-orchestrator-hub/client').then(m => m.remoteUrl('checkout-new'))`
108
+ checkoutnew: "promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote('checkout-new', 'checkoutnew')"
106
109
  },
107
110
  shared: { react: { singleton: true }, "react-dom": { singleton: true } }
108
111
  })
109
112
  ```
110
113
 
114
+ webpack pastes a `promise` remote into the bundle verbatim, outside of any module, and expects it to
115
+ resolve to the remote's *container* (`{ get, init }`), not to a URL. So the expression cannot import
116
+ this package: a bare `import('@mfe-orchestrator-hub/client')` there reaches the browser untouched and
117
+ fails with "Failed to resolve module specifier". It reads the client off a global instead, which the
118
+ package publishes as soon as it loads and again in `configure()`.
119
+
120
+ [`loadWebpackRemote(slug, scope)`](#loadwebpackremoteslug-scope) resolves the URL with `remoteUrl()`,
121
+ injects that `remoteEntry.js` once, and returns the container the script defines on
122
+ `globalThis[scope]`. The scope is the `name` the remote passes to its own `ModuleFederationPlugin`:
123
+ the console names each remote after its slug, without dashes and with `/` turned into `_`, which is
124
+ also the key the host imports from (`checkoutnew/Button`).
125
+
126
+ Keep the usual webpack bootstrap: `configure()` at the top of the entry file, then the rest of the app
127
+ behind `import("./bootstrap")`. A remote requested before `configure()` waits for it, but a remote
128
+ imported by the very chunk that calls `configure()` is loaded before that chunk runs.
129
+
111
130
  ### Where `backendUrl` and `projectId` come from
112
131
 
113
132
  The remotes above resolve themselves through this client, so the bundle has to carry the two
@@ -164,10 +183,13 @@ export function globalVariables(): Promise<Record<string, string>>
164
183
 
165
184
  /** The two ids, exposed for telemetry/debugging. */
166
185
  export function identities(): { sessionId: string; deviceId: string }
186
+
187
+ /** What a webpack `promise` remote resolves to. Also on globalThis.__MFE_ORCHESTRATOR__. */
188
+ export function loadWebpackRemote(slug: string, scope?: string): Promise<WebpackContainer>
167
189
  ```
168
190
 
169
- The types `Manifest`, `Microfrontend`, `GlobalVariable`, `Identities` and `OrchestratorConfig` are
170
- exported as well.
191
+ The types `Manifest`, `Microfrontend`, `GlobalVariable`, `Identities`, `OrchestratorConfig` and
192
+ `WebpackContainer` are exported as well.
171
193
 
172
194
  ### `remoteUrl(slug)`
173
195
 
@@ -185,6 +207,22 @@ in place it would request its chunks off a different version and mix two builds
185
207
 
186
208
  An unknown slug rejects with a message listing the slugs the environment does serve.
187
209
 
210
+ ### `loadWebpackRemote(slug, scope)`
211
+
212
+ Meant for the webpack config, through `globalThis.__MFE_ORCHESTRATOR__`, rather than for application
213
+ code. It:
214
+
215
+ - awaits `remoteUrl(slug)`, and waits for `configure()` first when it has not run yet (up to
216
+ `CONFIGURE_TIMEOUT_MS`, 10 seconds, then it rejects with the not configured error);
217
+ - injects the remote entry script once per URL: concurrent and later requests share the load, and a
218
+ failed load is forgotten so the next request tries again;
219
+ - reads the container off `globalThis[scope]` (left out, `scope` is the `nameToIntegrate` the
220
+ manifest gives the slug) and returns a `{ get, init }` passthrough whose `init` runs once, so two
221
+ hosts sharing a remote never initialize it twice.
222
+
223
+ It rejects with a message naming the slug and the URL when the script fails to load, and naming the
224
+ scope, plus the containers it did find on the page, when the script defines no container there.
225
+
188
226
  ### `globalVariables()`
189
227
 
190
228
  ```ts
package/dist/index.cjs CHANGED
@@ -227,6 +227,144 @@ var readIdentities = () => ({
227
227
  deviceId: persistentId("local", DEVICE_ID_KEY)
228
228
  });
229
229
 
230
+ // src/webpack.ts
231
+ var GLOBAL_NAMESPACE = "__MFE_ORCHESTRATOR__";
232
+ var CONFIGURE_TIMEOUT_MS = 1e4;
233
+ var globalScope = globalThis;
234
+ var publishGlobal = () => {
235
+ const existing = globalScope[GLOBAL_NAMESPACE];
236
+ const namespace = existing ?? {};
237
+ if (typeof namespace.loadWebpackRemote !== "function") {
238
+ namespace.loadWebpackRemote = loadWebpackRemote;
239
+ }
240
+ globalScope[GLOBAL_NAMESPACE] = namespace;
241
+ };
242
+ var configuredSignal = (state) => {
243
+ if (!state.configured) {
244
+ let resolve = () => {
245
+ };
246
+ const promise = new Promise((settle) => {
247
+ resolve = settle;
248
+ });
249
+ state.configured = { promise, resolve };
250
+ }
251
+ return state.configured;
252
+ };
253
+ var markConfigured = () => {
254
+ configuredSignal(getState()).resolve();
255
+ };
256
+ var whenConfigured = (caller) => {
257
+ const state = getState();
258
+ if (state.config) {
259
+ return Promise.resolve();
260
+ }
261
+ return new Promise((resolve, reject) => {
262
+ const timer = setTimeout(() => {
263
+ reject(
264
+ new Error(
265
+ `${notConfiguredMessage(caller, state.integration)}
266
+
267
+ The remote waited ${CONFIGURE_TIMEOUT_MS / 1e3} seconds for it. With webpack, call configure() in the entry file and load the rest of the app with import("./bootstrap") after it: a remote imported by the chunk that calls configure() is loaded before that chunk runs, so it can never see the configuration.`
268
+ )
269
+ );
270
+ }, CONFIGURE_TIMEOUT_MS);
271
+ configuredSignal(state).promise.then(() => {
272
+ clearTimeout(timer);
273
+ resolve();
274
+ });
275
+ });
276
+ };
277
+ var loadRemoteEntry = (url, slug) => {
278
+ const state = getState();
279
+ state.remoteEntries ??= /* @__PURE__ */ new Map();
280
+ const entries = state.remoteEntries;
281
+ const known = entries.get(url);
282
+ if (known) {
283
+ return known;
284
+ }
285
+ const load = new Promise((resolve, reject) => {
286
+ if (typeof document === "undefined") {
287
+ reject(new Error(`${PREFIX} loadWebpackRemote("${slug}") needs a browser document to load ${url} into, and there is none here.`));
288
+ return;
289
+ }
290
+ const script = document.createElement("script");
291
+ script.src = url;
292
+ script.async = true;
293
+ script.onload = () => resolve();
294
+ script.onerror = () => {
295
+ script.remove();
296
+ reject(
297
+ new Error(
298
+ `${PREFIX} the remote entry of "${slug}" failed to load from ${url}. The browser gives no reason for a failed script, so open the URL in a tab or look at the network panel: a 404 means the served version has no file at that path, a blocked request usually means a Content-Security-Policy (script-src) or a mixed content rule.`
299
+ )
300
+ );
301
+ };
302
+ document.head.appendChild(script);
303
+ });
304
+ entries.set(url, load);
305
+ load.catch(() => {
306
+ if (entries.get(url) === load) {
307
+ entries.delete(url);
308
+ }
309
+ });
310
+ return load;
311
+ };
312
+ var isContainer = (value) => typeof value === "object" && value !== null && typeof value.get === "function" && typeof value.init === "function";
313
+ var containerNames = () => {
314
+ const names = [];
315
+ for (const key of Object.keys(globalScope)) {
316
+ try {
317
+ if (isContainer(globalScope[key])) {
318
+ names.push(`"${key}"`);
319
+ }
320
+ } catch {
321
+ }
322
+ }
323
+ return names;
324
+ };
325
+ var missingContainerMessage = (slug, scope, url) => {
326
+ const found = containerNames();
327
+ return `${PREFIX} the remote entry of "${slug}" loaded from ${url}, but globalThis["${scope}"] is not a webpack container. The scope must be the name the remote passes to its own ModuleFederationPlugin, and the remote must keep its default library type ("var"). ${found.length > 0 ? `Containers on this page: ${found.join(", ")}.` : "No container is defined on this page at all."} A remote built with Vite is an ES module, not a webpack container, and cannot be loaded this way.`;
328
+ };
329
+ var guarded = (container) => {
330
+ const state = getState();
331
+ state.containers ??= /* @__PURE__ */ new WeakMap();
332
+ const known = state.containers.get(container);
333
+ if (known) {
334
+ return known;
335
+ }
336
+ let initialized = null;
337
+ const proxy = {
338
+ get: (module) => container.get(module),
339
+ init: (shareScope, initScope) => {
340
+ if (!initialized) {
341
+ initialized = { result: container.init(shareScope, initScope) };
342
+ }
343
+ return initialized.result;
344
+ }
345
+ };
346
+ state.containers.set(container, proxy);
347
+ return proxy;
348
+ };
349
+ var loadWebpackRemote = async (slug, scope) => {
350
+ const caller = `loadWebpackRemote("${slug}")`;
351
+ await whenConfigured(caller);
352
+ const url = await remoteUrl(slug);
353
+ const name = scope || (await manifest()).microfrontends.find((microfrontend) => microfrontend.slug === slug)?.nameToIntegrate;
354
+ if (!name) {
355
+ throw new Error(
356
+ `${PREFIX} ${caller} has no scope: none was passed and the manifest gives no nameToIntegrate for "${slug}". Pass the name the remote gives its ModuleFederationPlugin as the second argument.`
357
+ );
358
+ }
359
+ await loadRemoteEntry(url, slug);
360
+ const container = globalScope[name];
361
+ if (!isContainer(container)) {
362
+ throw new Error(missingContainerMessage(slug, name, url));
363
+ }
364
+ return guarded(container);
365
+ };
366
+ publishGlobal();
367
+
230
368
  // src/index.ts
231
369
  var withoutTrailingSlash = (value) => value.replace(/\/+$/, "");
232
370
  var resolveUserId = async (userId) => {
@@ -298,6 +436,7 @@ var fetchManifest = async (config) => {
298
436
  };
299
437
  var configure = (config) => {
300
438
  const state = getState();
439
+ publishGlobal();
301
440
  requireConfig(config, state.integration);
302
441
  const current = state.config;
303
442
  if (current) {
@@ -310,6 +449,7 @@ var configure = (config) => {
310
449
  }
311
450
  state.config = { ...config };
312
451
  warnAboutConfig(config);
452
+ markConfigured();
313
453
  };
314
454
  var setUserId = (userId) => {
315
455
  const state = getState();
@@ -376,9 +516,12 @@ var identities = () => {
376
516
  return state.identities;
377
517
  };
378
518
 
519
+ exports.CONFIGURE_TIMEOUT_MS = CONFIGURE_TIMEOUT_MS;
520
+ exports.GLOBAL_NAMESPACE = GLOBAL_NAMESPACE;
379
521
  exports.configure = configure;
380
522
  exports.globalVariables = globalVariables;
381
523
  exports.identities = identities;
524
+ exports.loadWebpackRemote = loadWebpackRemote;
382
525
  exports.manifest = manifest;
383
526
  exports.registerIntegration = registerIntegration;
384
527
  exports.remoteUrl = remoteUrl;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/state.ts","../src/storage.ts","../src/index.ts"],"names":["created"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Everything the client says when its configuration is wrong or absent.\n *\n * The two required options almost always arrive from build time environment variables, so the\n * failure the host sees is not \"a value is invalid\" but \"nothing reached the bundle\". Messages here\n * are written for that moment: they name the option, show what actually arrived, say where the real\n * value comes from, and print the exact call to write, in the flavour of the package the host uses.\n */\n\nexport const PREFIX = \"[@mfe-orchestrator-hub/client]\"\n\n/** Which package the host went through. Only decides which snippet an error prints. */\nexport type Integration = \"core\" | \"react\" | \"vue\" | \"angular\"\n\n/** The two options without which nothing can be requested. */\nexport type RequiredOption = \"backendUrl\" | \"projectId\"\n\nconst EXAMPLE_BACKEND_URL = \"https://console.mfe-orchestrator.dev/api\"\nconst EXAMPLE_PROJECT_ID = \"6f1b2c3d4e5f6a7b8c9d0e1f\"\n\nconst SNIPPETS: Record<Integration, string> = {\n core: `import { configure } from \"@mfe-orchestrator-hub/client\"\n\nconfigure({\n backendUrl: \"${EXAMPLE_BACKEND_URL}\",\n projectId: \"${EXAMPLE_PROJECT_ID}\"\n})`,\n react: `import { OrchestratorProvider } from \"@mfe-orchestrator-hub/client-react\"\n\n<OrchestratorProvider config={{ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }}>\n <App />\n</OrchestratorProvider>`,\n vue: `import { createOrchestrator } from \"@mfe-orchestrator-hub/client-vue\"\n\napp.use(createOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }))`,\n angular: `import { provideOrchestrator } from \"@mfe-orchestrator-hub/client-angular\"\n\nbootstrapApplication(AppComponent, {\n providers: [provideOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" })]\n})`\n}\n\nconst WHERE: Record<Integration, string> = {\n core: \"Call it once, at the very top of the host entry point, before anything imports a remote.\",\n react: \"Render it above every component that resolves a remote. Better still, call configure() at the very top of the entry point: a bundler may import a remote before React mounts.\",\n vue: \"Install the plugin before mounting the app. Better still, call configure() at the very top of the entry point: a bundler may import a remote before the app is created.\",\n angular: \"Pass it to bootstrapApplication(). Better still, call configure() at the very top of main.ts: a lazily loaded remote must find the client already configured.\"\n}\n\nconst WHAT_IT_IS: Record<RequiredOption, string> = {\n backendUrl: `It is the base URL of the console API, protocol included, ex. \"${EXAMPLE_BACKEND_URL}\". A path on the same origin as the host, ex. \"/api\", works too.`,\n projectId: `It is the id of the project in the console: open the project and copy it from its page, ex. \"${EXAMPLE_PROJECT_ID}\".`\n}\n\n/** The name the value travels under from the bundler config into the bundle, per toolchain. */\nconst BUILD_VARIABLE: Record<RequiredOption, { vite: string; webpack: string }> = {\n backendUrl: { vite: \"VITE_MFE_BACKEND_URL\", webpack: \"MFE_BACKEND_URL\" },\n projectId: { vite: \"VITE_MFE_PROJECT_ID\", webpack: \"MFE_PROJECT_ID\" }\n}\n\n/**\n * What an option that was never substituted into the bundle looks like.\n *\n * The bundler config is named before the .env file on purpose: it is where the console writes both\n * values when it generates the config, so it is where they are missing from when they are missing.\n */\nconst missingEnvHint = (option: RequiredOption): string =>\n `Nothing arrived here at all, which is what a value that never reached the bundle looks like: check ${BUILD_VARIABLE[option].vite} (Vite) or ${BUILD_VARIABLE[option].webpack} (webpack) in the build that produced this bundle. The generated configs carry it in the \"define\" block of vite.config, or in the DefinePlugin of webpack.config, so look there first; declared only in a .env file the build never reads, it looks exactly like this.`\n\n/** Values that mean \"the template was never filled in\". */\nconst PLACEHOLDER = /^(…|\\.{3}|undefined|null|nan|<[^>]*>|\\{\\{[^}]*\\}\\}|\\$\\{[^}]*\\}|your[-_ ]?[a-z]*|x{3,}|change[-_ ]?me|todo|tbd)$/i\n\n/** Long values are cut: an error message is not the place to print a whole JWT. */\nconst quoted = (value: string): string => JSON.stringify(value.length > 120 ? `${value.slice(0, 120)}…` : value)\n\nconst described = (value: unknown): string => {\n if (value === null) {\n return \"null\"\n }\n if (Array.isArray(value)) {\n return \"an array\"\n }\n const type = typeof value\n return type === \"object\" || type === \"function\" ? `a ${type}` : `a ${type} (${String(value)})`\n}\n\n/** Same key modulo case and separators: projectID, project_id, PROJECT-ID all collapse onto projectid. */\nconst normalized = (key: string): string => key.toLowerCase().replace(/[^a-z0-9]/g, \"\")\n\nconst ALIASES: Record<RequiredOption, string[]> = {\n backendUrl: [\"backendurl\", \"backendbaseurl\", \"apiurl\", \"baseurl\", \"consoleurl\", \"url\", \"backend\"],\n projectId: [\"projectid\", \"project\", \"idproject\", \"projectuuid\", \"projectkey\"]\n}\n\n/**\n * The key the host actually wrote, when it looks like a misspelling of the one that is missing.\n * `projectID` is by far the most common: it is silently ignored, so without this the message would\n * claim the option is absent while the developer stares at a line that clearly sets it.\n */\nconst confusableKey = (option: RequiredOption, config: unknown): string | undefined => {\n if (typeof config !== \"object\" || config === null) {\n return undefined\n }\n const candidates = ALIASES[option]\n return Object.keys(config).find(key => key !== option && candidates.includes(normalized(key)))\n}\n\n/** One thing that is wrong with one option, already spelled out. */\nexport interface ConfigProblem {\n option: RequiredOption\n /** Predicate completing \"<option> …\", ex. `is missing`. */\n what: string\n /** Extra lines, printed under the option, that say how to fix this particular case. */\n hints: string[]\n}\n\nconst problem = (option: RequiredOption, what: string, ...hints: (string | undefined)[]): ConfigProblem => ({\n option,\n what,\n hints: [WHAT_IT_IS[option], ...hints].filter((hint): hint is string => Boolean(hint))\n})\n\n/**\n * A backendUrl the client can actually build a request on: an absolute http(s) URL, or a path on the\n * host's own origin, which `fetch` resolves against the page.\n */\nconst diagnoseBackendUrl = (value: string): ConfigProblem | null => {\n const trimmed = value.trim()\n if (trimmed.startsWith(\"/\")) {\n return null\n }\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, which is not a URL`,\n trimmed.includes(\".\") || trimmed.includes(\":\")\n ? `It looks like a host without a protocol: write \"https://${trimmed}\" instead, or \"/${trimmed.replace(/^\\/+/, \"\")}\" if the console API answers on the same origin as this page.`\n : undefined\n )\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, whose \"${parsed.protocol.replace(\":\", \"\")}\" scheme is neither http nor https`,\n 'A bare \"host:port\" is read as a scheme: write \"http://localhost:3000/api\", not \"localhost:3000/api\".'\n )\n }\n return null\n}\n\n/** Everything wrong with one required option, or null when it is usable. */\nconst diagnose = (option: RequiredOption, config: unknown): ConfigProblem | null => {\n const value = (config as Record<string, unknown> | null | undefined)?.[option]\n const typo = confusableKey(option, config)\n const typoHint = typo ? `The configuration carries \"${typo}\", which the client ignores. The option is spelled \"${option}\".` : undefined\n\n if (value === undefined || value === null) {\n return problem(option, value === null ? \"is null\" : \"is missing\", typoHint, typo ? undefined : missingEnvHint(option))\n }\n if (typeof value !== \"string\") {\n return problem(option, `is ${described(value)}, not a string`, typoHint)\n }\n if (value.trim() === \"\") {\n return problem(option, value === \"\" ? \"is an empty string\" : \"holds nothing but whitespace\", typoHint, missingEnvHint(option))\n }\n if (PLACEHOLDER.test(value.trim())) {\n const looksLikeAnUnsetVariable = /^(undefined|null|nan)$/i.test(value.trim())\n return problem(option, `is still the placeholder ${quoted(value)}`, typoHint, looksLikeAnUnsetVariable ? missingEnvHint(option) : undefined)\n }\n if (option === \"projectId\" && value.trim() !== value) {\n // Percent encoded into the path, so the padding would travel to the backend as %20.\n return problem(\n \"projectId\",\n `is ${quoted(value)}, padded with whitespace`,\n \"Trim the value: it is percent encoded into the manifest URL, so the spaces would reach the backend as part of the id.\"\n )\n }\n return option === \"backendUrl\" ? diagnoseBackendUrl(value) : null\n}\n\n/** Every problem of a configuration, in the order the options are declared. Empty means usable. */\nexport const diagnoseConfig = (config: unknown): ConfigProblem[] =>\n ([\"backendUrl\", \"projectId\"] as const).map(option => diagnose(option, config)).filter((found): found is ConfigProblem => found !== null)\n\nconst bulleted = (problems: ConfigProblem[]): string => problems.map(({ option, what, hints }) => [` • ${option} ${what}.`, ...hints.map(hint => ` → ${hint}`)].join(\"\\n\")).join(\"\\n\")\n\nconst indented = (block: string): string =>\n block\n .split(\"\\n\")\n .map(line => (line ? ` ${line}` : line))\n .join(\"\\n\")\n\nconst howToConfigure = (integration: Integration): string => `Configure the client like this:\\n\\n${indented(SNIPPETS[integration])}\\n\\n${WHERE[integration]}`\n\nconst listed = (options: RequiredOption[]): string => (options.length > 1 ? `${options.slice(0, -1).join(\", \")} and ${options.at(-1)}` : String(options[0]))\n\n/** The message thrown by `configure()` when what it received cannot be used. */\nexport const invalidConfigMessage = (problems: ConfigProblem[], integration: Integration): string => {\n const options = problems.map(({ option }) => option)\n const headline = `${PREFIX} configure() cannot start the client: ${listed(options)} ${options.length > 1 ? \"are\" : \"is\"} not usable.`\n return `${headline}\\n\\n${bulleted(problems)}\\n\\n${howToConfigure(integration)}`\n}\n\n/** The message thrown by `configure()` when it did not even receive an object. */\nexport const noConfigMessage = (config: unknown, integration: Integration): string =>\n `${PREFIX} configure() was called with ${config === undefined ? \"no argument\" : described(config)} instead of a configuration object. It needs at least backendUrl and projectId.\\n\\n${howToConfigure(integration)}`\n\n/** The message every read rejects with while the client has no configuration at all. */\nexport const notConfiguredMessage = (caller: string, integration: Integration): string =>\n `${PREFIX} the client is not configured: ${caller} was called before configure() ever ran, so neither backendUrl nor projectId is known and no manifest can be requested.\\n\\n${howToConfigure(integration)}`\n","import type { Integration } from \"./errors\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\n\nexport interface OrchestratorState {\n config: OrchestratorConfig | null\n manifestPromise: Promise<Manifest> | null\n identities: Identities | null\n /** Set by the framework adapters as they load, so an error prints the snippet of their own API. */\n integration: Integration\n}\n\n/**\n * The state lives on `globalThis` under this key, not in a module scope variable.\n *\n * A host can end up with two copies of this package loaded at once: the app imports the ESM build\n * while something else pulls the CJS one, or the bundler config and the app resolve to different\n * chunks. Two module scopes would mean two configurations and two manifest requests, which is\n * exactly what the contract forbids. One well known global slot makes the singleton real.\n */\nexport const STATE_KEY = \"__mfe_orchestrator_client__\"\n\nconst globalSlot = globalThis as typeof globalThis & Record<typeof STATE_KEY, OrchestratorState | undefined>\n\nexport const getState = (): OrchestratorState => {\n let state = globalSlot[STATE_KEY]\n if (!state) {\n state = { config: null, manifestPromise: null, identities: null, integration: \"core\" }\n globalSlot[STATE_KEY] = state\n }\n return state\n}\n","import type { Identities } from \"./types\"\n\nexport const SESSION_ID_KEY = \"mfe-orchestrator.sessionId\"\nexport const DEVICE_ID_KEY = \"mfe-orchestrator.deviceId\"\n\nconst PROBE_KEY = \"mfe-orchestrator.probe\"\n\ntype StorageKind = \"local\" | \"session\"\n\n/**\n * Ids minted while storage was unusable. They live for the lifetime of the page so that, even\n * without storage, every request of this page load carries one stable pair of ids.\n */\nconst inMemoryIds = new Map<string, string>()\n\nconst uuidFromRandomBytes = (bytes: Uint8Array): string => {\n bytes[6] = (bytes[6] & 0x0f) | 0x40\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n const hex: string[] = []\n for (const byte of bytes) {\n hex.push(byte.toString(16).padStart(2, \"0\"))\n }\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`\n}\n\n/**\n * A v4 UUID. `crypto.randomUUID` is the intended path; the two fallbacks only exist so that a page\n * served over plain http, or an exotic runtime, still gets an id instead of an exception.\n */\nexport const newId = (): string => {\n const cryptoApi = globalThis.crypto\n try {\n if (typeof cryptoApi?.randomUUID === \"function\") {\n return cryptoApi.randomUUID()\n }\n if (typeof cryptoApi?.getRandomValues === \"function\") {\n return uuidFromRandomBytes(cryptoApi.getRandomValues(new Uint8Array(16)))\n }\n } catch {\n // fall through to the non cryptographic fallback\n }\n const bytes = new Uint8Array(16)\n for (let index = 0; index < bytes.length; index++) {\n bytes[index] = Math.floor(Math.random() * 256)\n }\n return uuidFromRandomBytes(bytes)\n}\n\n/**\n * The requested storage, or `null` when it is missing or unusable.\n *\n * Both the property access and the write can throw: Safari in private mode exposes the object and\n * then refuses `setItem`, some hardened browsers throw a SecurityError on the access itself. The\n * write probe is the only reliable way to tell a usable storage from a decorative one.\n */\nconst openStorage = (kind: StorageKind): Storage | null => {\n try {\n const storage = kind === \"local\" ? globalThis.localStorage : globalThis.sessionStorage\n if (!storage) {\n return null\n }\n storage.setItem(PROBE_KEY, \"1\")\n storage.removeItem(PROBE_KEY)\n return storage\n } catch {\n return null\n }\n}\n\n/**\n * The id under `key`, read from storage and created on first use. Falls back to an id kept in\n * memory when storage cannot be used, so this never throws out of the SDK.\n */\nconst persistentId = (kind: StorageKind, key: string): string => {\n const storage = openStorage(kind)\n if (storage) {\n try {\n const stored = storage.getItem(key)\n if (stored) {\n return stored\n }\n const created = newId()\n storage.setItem(key, created)\n return created\n } catch {\n // storage passed the probe and failed anyway: keep going with an in memory id\n }\n }\n const remembered = inMemoryIds.get(key)\n if (remembered) {\n return remembered\n }\n const created = newId()\n inMemoryIds.set(key, created)\n return created\n}\n\n/** Reads, and creates when needed, the session and device ids. */\nexport const readIdentities = (): Identities => ({\n sessionId: persistentId(\"session\", SESSION_ID_KEY),\n deviceId: persistentId(\"local\", DEVICE_ID_KEY)\n})\n","import { diagnoseConfig, type Integration, invalidConfigMessage, noConfigMessage, notConfiguredMessage, PREFIX } from \"./errors\"\nimport { getState } from \"./state\"\nimport { readIdentities } from \"./storage\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\n\nexport type { ConfigProblem, Integration } from \"./errors\"\nexport type { GlobalVariable, Identities, Manifest, Microfrontend, OrchestratorConfig } from \"./types\"\n\nconst withoutTrailingSlash = (value: string): string => value.replace(/\\/+$/, \"\")\n\nconst resolveUserId = async (userId: OrchestratorConfig[\"userId\"]): Promise<string | undefined> => {\n const value = typeof userId === \"function\" ? await userId() : userId\n return value === undefined || value === null || value === \"\" ? undefined : String(value)\n}\n\n/** Everything but the identity: the part of the configuration that is fixed for a page load. */\nconst sameTarget = (left: OrchestratorConfig, right: OrchestratorConfig): boolean =>\n left.backendUrl === right.backendUrl && left.projectId === right.projectId && left.environment === right.environment\n\nconst sameConfig = (left: OrchestratorConfig, right: OrchestratorConfig): boolean => sameTarget(left, right) && left.userId === right.userId\n\n/**\n * Whether replacing the identity would change nothing. Two getters are never considered equal, even the\n * same one twice: what a function returns is exactly what this side cannot know, so a host handing one\n * over is taken at its word and the manifest is re-fetched.\n */\nconst sameUserId = (left: OrchestratorConfig[\"userId\"], right: OrchestratorConfig[\"userId\"]): boolean => typeof left !== \"function\" && typeof right !== \"function\" && left === right\n\n/**\n * Rejects a configuration the client could not use, with a message that names the option, shows what\n * actually arrived and prints the call to write. environment is deliberately not required: without\n * it the backend resolves it from the domain. It is still checked for type, because a non string\n * there would silently end up percent encoded into the path.\n */\nconst requireConfig = (config: OrchestratorConfig, integration: Integration): void => {\n if (typeof config !== \"object\" || config === null) {\n throw new Error(noConfigMessage(config, integration))\n }\n const problems = diagnoseConfig(config)\n if (problems.length > 0) {\n throw new Error(invalidConfigMessage(problems, integration))\n }\n if (config.environment !== undefined && config.environment !== null && typeof config.environment !== \"string\") {\n throw new Error(\n `${PREFIX} configure() received environment as a ${typeof config.environment}, not a string. Pass the environment slug as it appears in the console, ex. \"DEV\", or leave it out to let the backend resolve it from the domain of this page.`\n )\n }\n}\n\n/** Notices about a stored configuration that works but probably does not do what the host meant. */\nconst warnAboutConfig = (config: OrchestratorConfig): void => {\n if (typeof config.environment === \"string\" && config.environment.trim() === \"\") {\n console.warn(\n `${PREFIX} configure() received an empty environment, so the client falls back to the auto routes and the backend resolves the environment from the domain of this page. Remove the option if that is what you want, or check the variable that feeds it.`\n )\n }\n}\n\n/**\n * Two shapes, one per route family. With an explicit environment the slug is the last segment; with\n * no environment the \"auto\" segment takes its place before the project id and the backend resolves\n * the environment from the domain the request comes from.\n */\nconst manifestPath = (config: OrchestratorConfig): string => {\n const projectId = encodeURIComponent(config.projectId)\n return config.environment ? `/serve/all/${projectId}/${encodeURIComponent(config.environment)}` : `/serve/all/auto/${projectId}`\n}\n\nconst manifestUrl = async (config: OrchestratorConfig): Promise<string> => {\n const { sessionId, deviceId } = identities()\n const query = new URLSearchParams({ mfeSessionId: sessionId, mfeDeviceId: deviceId })\n // Resolved as late as possible: the host may only know the user after its own auth round trip.\n const userId = await resolveUserId(config.userId)\n if (userId) {\n query.set(\"mfeUserId\", userId)\n }\n return `${withoutTrailingSlash(config.backendUrl)}${manifestPath(config)}?${query.toString()}`\n}\n\n/**\n * What a status usually means on this route. The backend answers the same 404 for an unknown project\n * and for an unknown environment, and the two are indistinguishable from here, so both are named.\n */\nconst statusHint = (status: number, config: OrchestratorConfig): string => {\n if (status === 404) {\n const environment = config.environment\n ? `the environment \"${config.environment}\" does not exist in it`\n : \"no environment of that project declares the domain this page is served on, which is what the auto route resolves on\"\n return `\\n\\nA 404 on this route means the backend did not find what the URL names: either the project id \"${config.projectId}\" is not a project of this console, or ${environment}. Check both in the console, and check that backendUrl points at the console API of the same instance.`\n }\n if (status === 401 || status === 403) {\n return `\\n\\nThe console refused the request. Check that the project id \"${config.projectId}\" belongs to the instance backendUrl points at, and that this domain is allowed to read its manifest.`\n }\n return \"\"\n}\n\nconst fetchManifest = async (config: OrchestratorConfig): Promise<Manifest> => {\n const url = await manifestUrl(config)\n // No retry in v1: whatever fetch throws travels straight to the caller.\n const response = await fetch(url, { headers: { accept: \"application/json\" } })\n if (!response.ok) {\n throw new Error(`${PREFIX} the manifest request failed with ${response.status} ${response.statusText}. GET ${url}${statusHint(response.status, config)}`)\n }\n const payload = (await response.json()) as Partial<Manifest> | null\n return {\n globalVariables: payload?.globalVariables ?? [],\n microfrontends: payload?.microfrontends ?? []\n }\n}\n\n/**\n * Hands the client its configuration. Call it once, synchronously, before any remote is imported.\n *\n * `backendUrl` and `projectId` are required. `environment` is not: omitting it makes the client use\n * the \"auto\" routes, where the backend resolves the environment from the domain of the host page.\n *\n * Idempotent: calling it again with the same options is a no op, so a framework provider may safely\n * call it on every render. A second call with different options is ignored, with a warning, because\n * the manifest of this page load may already be in flight or resolved. The user is the exception, and\n * it changes through `setUserId()`, not through a second call here.\n */\nexport const configure = (config: OrchestratorConfig): void => {\n const state = getState()\n requireConfig(config, state.integration)\n const current = state.config\n if (current) {\n if (!sameConfig(current, config)) {\n console.warn(\n sameTarget(current, config)\n ? `${PREFIX} configure() was called again with a different userId. The configuration is fixed for this page load, so this one is ignored: call setUserId() instead, which is the supported way to change the user mid session and also drops the memoized manifest, so the next read is decided on the new identity.`\n : `${PREFIX} configure() was called again with a different configuration. The first one is kept: ${JSON.stringify({ backendUrl: current.backendUrl, projectId: current.projectId, environment: current.environment })}.`\n )\n }\n return\n }\n state.config = { ...config }\n warnAboutConfig(config)\n}\n\n/**\n * Replaces the identity the backend decides a user based canary on, after the client was configured.\n *\n * `configure()` is deliberately once only, and this is the one option that legitimately changes while\n * the page is alive: a login, a logout, an account switch. So it gets its own setter, and that setter\n * does what `configure()` must not — it drops the memoized manifest, so the next `manifest()`,\n * `remoteUrl()` or `globalVariables()` asks the backend again and is answered for the new user.\n *\n * Pass `undefined` on logout: the next request then carries no `mfeUserId` at all, which is what makes\n * the backend hand out the stable version again.\n *\n * What this does NOT do is reload the remotes already imported. The federation runtime keeps the\n * container it has, so a microfrontend already on the page stays on the version drawn for the previous\n * user, and only remotes resolved after this call see the new one. When the whole page must be\n * consistent, follow the identity change with a reload; when the host mounts its remotes behind its own\n * auth guard, calling this before the guard opens is enough.\n *\n * Setting the same plain value again is a no op, so an auth store may call it on every emission without\n * costing a request. A getter is always taken as a change, since what it returns is precisely what this\n * side cannot know.\n *\n * A request already in flight is not cancelled: whoever is awaiting it still receives the manifest of\n * the previous identity. Only the memo is dropped.\n */\nexport const setUserId = (userId: OrchestratorConfig[\"userId\"]): void => {\n const state = getState()\n const current = state.config\n if (!current) {\n throw new Error(notConfiguredMessage(\"setUserId()\", state.integration))\n }\n if (sameUserId(current.userId, userId)) {\n return\n }\n state.config = { ...current, userId }\n state.manifestPromise = null\n}\n\n/**\n * @internal Lets a framework adapter say which package the host is really using, so a configuration\n * error prints the snippet of that API instead of the bare `configure()` one. Idempotent, and never\n * needed by an application: the adapters call it as they load.\n */\nexport const registerIntegration = (integration: Integration): void => {\n getState().integration = integration\n}\n\n/**\n * The whole manifest of the environment, fetched once per page load and memoized as a promise, so\n * that concurrent callers share the single request in flight.\n *\n * A successful result is memoized for good. A failed attempt is not: the memo is dropped when the\n * shared attempt settles as rejected, so the next caller starts a fresh request. That is not a retry\n * — nothing here loops or backs off — it only means one flaky lookup at boot does not condemn the\n * page to reject every `remoteUrl()` until a full reload.\n */\nconst loadManifest = (caller: string): Promise<Manifest> => {\n const state = getState()\n const config = state.config\n if (!config) {\n // Not memoized: the host may still configure the client and try again.\n return Promise.reject(new Error(notConfiguredMessage(caller, state.integration)))\n }\n if (!state.manifestPromise) {\n // Assigned before the first await inside fetchManifest, which is what makes N concurrent\n // callers collapse onto one request.\n const attempt = fetchManifest(config)\n state.manifestPromise = attempt\n // Cleared once, when the shared attempt settles, not in each caller's own catch: every\n // caller already waiting on this attempt still gets its rejection. The identity check keeps\n // a late failure from evicting a newer attempt.\n attempt.catch(() => {\n if (state.manifestPromise === attempt) {\n state.manifestPromise = null\n }\n })\n }\n return state.manifestPromise\n}\n\n/** The whole manifest of the environment. See `loadManifest` for the memoization contract. */\nexport const manifest = (): Promise<Manifest> => loadManifest(\"manifest()\")\n\n/**\n * The ready to use, version pinned URL of a remote. Awaits the manifest internally.\n *\n * The returned URL is used verbatim: the host never parses the version out of it and never strips\n * the `_v/<version>/` segment, or a classic script would load its chunks off another version.\n */\nexport const remoteUrl = async (slug: string): Promise<string> => {\n const { microfrontends } = await loadManifest(`remoteUrl(\"${slug}\")`)\n const found = microfrontends.find(microfrontend => microfrontend.slug === slug)\n if (!found) {\n const available = microfrontends.map(microfrontend => `\"${microfrontend.slug}\"`).join(\", \")\n const environment = getState().config?.environment\n // With no configured environment the host cannot name the one it was served: only the backend knows.\n const where = environment ? `environment \"${environment}\"` : \"the environment resolved from this domain\"\n throw new Error(`${PREFIX} unknown microfrontend slug \"${slug}\". Available in ${where}: ${available || \"none, this environment serves no microfrontend\"}.`)\n }\n if (!found.url) {\n throw new Error(`${PREFIX} the microfrontend \"${slug}\" is in the manifest but carries no url. Check its deployment in the console.`)\n }\n return found.url\n}\n\n/** The global variables of the environment, as a plain object. */\nexport const globalVariables = async (): Promise<Record<string, string>> => {\n const { globalVariables: variables } = await loadManifest(\"globalVariables()\")\n const result: Record<string, string> = {}\n for (const variable of variables) {\n if (variable && typeof variable.key === \"string\") {\n result[variable.key] = variable.value\n }\n }\n return result\n}\n\n/**\n * The session and device ids of this page, exposed for telemetry and debugging. Created on first\n * use and stable for the lifetime of the page, whether or not storage is available.\n */\nexport const identities = (): Identities => {\n const state = getState()\n if (!state.identities) {\n state.identities = readIdentities()\n }\n return state.identities\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/state.ts","../src/storage.ts","../src/webpack.ts","../src/index.ts"],"names":["created"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Everything the client says when its configuration is wrong or absent.\n *\n * The two required options almost always arrive from build time environment variables, so the\n * failure the host sees is not \"a value is invalid\" but \"nothing reached the bundle\". Messages here\n * are written for that moment: they name the option, show what actually arrived, say where the real\n * value comes from, and print the exact call to write, in the flavour of the package the host uses.\n */\n\nexport const PREFIX = \"[@mfe-orchestrator-hub/client]\"\n\n/** Which package the host went through. Only decides which snippet an error prints. */\nexport type Integration = \"core\" | \"react\" | \"vue\" | \"angular\"\n\n/** The two options without which nothing can be requested. */\nexport type RequiredOption = \"backendUrl\" | \"projectId\"\n\nconst EXAMPLE_BACKEND_URL = \"https://console.mfe-orchestrator.dev/api\"\nconst EXAMPLE_PROJECT_ID = \"6f1b2c3d4e5f6a7b8c9d0e1f\"\n\nconst SNIPPETS: Record<Integration, string> = {\n core: `import { configure } from \"@mfe-orchestrator-hub/client\"\n\nconfigure({\n backendUrl: \"${EXAMPLE_BACKEND_URL}\",\n projectId: \"${EXAMPLE_PROJECT_ID}\"\n})`,\n react: `import { OrchestratorProvider } from \"@mfe-orchestrator-hub/client-react\"\n\n<OrchestratorProvider config={{ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }}>\n <App />\n</OrchestratorProvider>`,\n vue: `import { createOrchestrator } from \"@mfe-orchestrator-hub/client-vue\"\n\napp.use(createOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }))`,\n angular: `import { provideOrchestrator } from \"@mfe-orchestrator-hub/client-angular\"\n\nbootstrapApplication(AppComponent, {\n providers: [provideOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" })]\n})`\n}\n\nconst WHERE: Record<Integration, string> = {\n core: \"Call it once, at the very top of the host entry point, before anything imports a remote.\",\n react: \"Render it above every component that resolves a remote. Better still, call configure() at the very top of the entry point: a bundler may import a remote before React mounts.\",\n vue: \"Install the plugin before mounting the app. Better still, call configure() at the very top of the entry point: a bundler may import a remote before the app is created.\",\n angular: \"Pass it to bootstrapApplication(). Better still, call configure() at the very top of main.ts: a lazily loaded remote must find the client already configured.\"\n}\n\nconst WHAT_IT_IS: Record<RequiredOption, string> = {\n backendUrl: `It is the base URL of the console API, protocol included, ex. \"${EXAMPLE_BACKEND_URL}\". A path on the same origin as the host, ex. \"/api\", works too.`,\n projectId: `It is the id of the project in the console: open the project and copy it from its page, ex. \"${EXAMPLE_PROJECT_ID}\".`\n}\n\n/** The name the value travels under from the bundler config into the bundle, per toolchain. */\nconst BUILD_VARIABLE: Record<RequiredOption, { vite: string; webpack: string }> = {\n backendUrl: { vite: \"VITE_MFE_BACKEND_URL\", webpack: \"MFE_BACKEND_URL\" },\n projectId: { vite: \"VITE_MFE_PROJECT_ID\", webpack: \"MFE_PROJECT_ID\" }\n}\n\n/**\n * What an option that was never substituted into the bundle looks like.\n *\n * The bundler config is named before the .env file on purpose: it is where the console writes both\n * values when it generates the config, so it is where they are missing from when they are missing.\n */\nconst missingEnvHint = (option: RequiredOption): string =>\n `Nothing arrived here at all, which is what a value that never reached the bundle looks like: check ${BUILD_VARIABLE[option].vite} (Vite) or ${BUILD_VARIABLE[option].webpack} (webpack) in the build that produced this bundle. The generated configs carry it in the \"define\" block of vite.config, or in the DefinePlugin of webpack.config, so look there first; declared only in a .env file the build never reads, it looks exactly like this.`\n\n/** Values that mean \"the template was never filled in\". */\nconst PLACEHOLDER = /^(…|\\.{3}|undefined|null|nan|<[^>]*>|\\{\\{[^}]*\\}\\}|\\$\\{[^}]*\\}|your[-_ ]?[a-z]*|x{3,}|change[-_ ]?me|todo|tbd)$/i\n\n/** Long values are cut: an error message is not the place to print a whole JWT. */\nconst quoted = (value: string): string => JSON.stringify(value.length > 120 ? `${value.slice(0, 120)}…` : value)\n\nconst described = (value: unknown): string => {\n if (value === null) {\n return \"null\"\n }\n if (Array.isArray(value)) {\n return \"an array\"\n }\n const type = typeof value\n return type === \"object\" || type === \"function\" ? `a ${type}` : `a ${type} (${String(value)})`\n}\n\n/** Same key modulo case and separators: projectID, project_id, PROJECT-ID all collapse onto projectid. */\nconst normalized = (key: string): string => key.toLowerCase().replace(/[^a-z0-9]/g, \"\")\n\nconst ALIASES: Record<RequiredOption, string[]> = {\n backendUrl: [\"backendurl\", \"backendbaseurl\", \"apiurl\", \"baseurl\", \"consoleurl\", \"url\", \"backend\"],\n projectId: [\"projectid\", \"project\", \"idproject\", \"projectuuid\", \"projectkey\"]\n}\n\n/**\n * The key the host actually wrote, when it looks like a misspelling of the one that is missing.\n * `projectID` is by far the most common: it is silently ignored, so without this the message would\n * claim the option is absent while the developer stares at a line that clearly sets it.\n */\nconst confusableKey = (option: RequiredOption, config: unknown): string | undefined => {\n if (typeof config !== \"object\" || config === null) {\n return undefined\n }\n const candidates = ALIASES[option]\n return Object.keys(config).find(key => key !== option && candidates.includes(normalized(key)))\n}\n\n/** One thing that is wrong with one option, already spelled out. */\nexport interface ConfigProblem {\n option: RequiredOption\n /** Predicate completing \"<option> …\", ex. `is missing`. */\n what: string\n /** Extra lines, printed under the option, that say how to fix this particular case. */\n hints: string[]\n}\n\nconst problem = (option: RequiredOption, what: string, ...hints: (string | undefined)[]): ConfigProblem => ({\n option,\n what,\n hints: [WHAT_IT_IS[option], ...hints].filter((hint): hint is string => Boolean(hint))\n})\n\n/**\n * A backendUrl the client can actually build a request on: an absolute http(s) URL, or a path on the\n * host's own origin, which `fetch` resolves against the page.\n */\nconst diagnoseBackendUrl = (value: string): ConfigProblem | null => {\n const trimmed = value.trim()\n if (trimmed.startsWith(\"/\")) {\n return null\n }\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, which is not a URL`,\n trimmed.includes(\".\") || trimmed.includes(\":\")\n ? `It looks like a host without a protocol: write \"https://${trimmed}\" instead, or \"/${trimmed.replace(/^\\/+/, \"\")}\" if the console API answers on the same origin as this page.`\n : undefined\n )\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, whose \"${parsed.protocol.replace(\":\", \"\")}\" scheme is neither http nor https`,\n 'A bare \"host:port\" is read as a scheme: write \"http://localhost:3000/api\", not \"localhost:3000/api\".'\n )\n }\n return null\n}\n\n/** Everything wrong with one required option, or null when it is usable. */\nconst diagnose = (option: RequiredOption, config: unknown): ConfigProblem | null => {\n const value = (config as Record<string, unknown> | null | undefined)?.[option]\n const typo = confusableKey(option, config)\n const typoHint = typo ? `The configuration carries \"${typo}\", which the client ignores. The option is spelled \"${option}\".` : undefined\n\n if (value === undefined || value === null) {\n return problem(option, value === null ? \"is null\" : \"is missing\", typoHint, typo ? undefined : missingEnvHint(option))\n }\n if (typeof value !== \"string\") {\n return problem(option, `is ${described(value)}, not a string`, typoHint)\n }\n if (value.trim() === \"\") {\n return problem(option, value === \"\" ? \"is an empty string\" : \"holds nothing but whitespace\", typoHint, missingEnvHint(option))\n }\n if (PLACEHOLDER.test(value.trim())) {\n const looksLikeAnUnsetVariable = /^(undefined|null|nan)$/i.test(value.trim())\n return problem(option, `is still the placeholder ${quoted(value)}`, typoHint, looksLikeAnUnsetVariable ? missingEnvHint(option) : undefined)\n }\n if (option === \"projectId\" && value.trim() !== value) {\n // Percent encoded into the path, so the padding would travel to the backend as %20.\n return problem(\n \"projectId\",\n `is ${quoted(value)}, padded with whitespace`,\n \"Trim the value: it is percent encoded into the manifest URL, so the spaces would reach the backend as part of the id.\"\n )\n }\n return option === \"backendUrl\" ? diagnoseBackendUrl(value) : null\n}\n\n/** Every problem of a configuration, in the order the options are declared. Empty means usable. */\nexport const diagnoseConfig = (config: unknown): ConfigProblem[] =>\n ([\"backendUrl\", \"projectId\"] as const).map(option => diagnose(option, config)).filter((found): found is ConfigProblem => found !== null)\n\nconst bulleted = (problems: ConfigProblem[]): string => problems.map(({ option, what, hints }) => [` • ${option} ${what}.`, ...hints.map(hint => ` → ${hint}`)].join(\"\\n\")).join(\"\\n\")\n\nconst indented = (block: string): string =>\n block\n .split(\"\\n\")\n .map(line => (line ? ` ${line}` : line))\n .join(\"\\n\")\n\nconst howToConfigure = (integration: Integration): string => `Configure the client like this:\\n\\n${indented(SNIPPETS[integration])}\\n\\n${WHERE[integration]}`\n\nconst listed = (options: RequiredOption[]): string => (options.length > 1 ? `${options.slice(0, -1).join(\", \")} and ${options.at(-1)}` : String(options[0]))\n\n/** The message thrown by `configure()` when what it received cannot be used. */\nexport const invalidConfigMessage = (problems: ConfigProblem[], integration: Integration): string => {\n const options = problems.map(({ option }) => option)\n const headline = `${PREFIX} configure() cannot start the client: ${listed(options)} ${options.length > 1 ? \"are\" : \"is\"} not usable.`\n return `${headline}\\n\\n${bulleted(problems)}\\n\\n${howToConfigure(integration)}`\n}\n\n/** The message thrown by `configure()` when it did not even receive an object. */\nexport const noConfigMessage = (config: unknown, integration: Integration): string =>\n `${PREFIX} configure() was called with ${config === undefined ? \"no argument\" : described(config)} instead of a configuration object. It needs at least backendUrl and projectId.\\n\\n${howToConfigure(integration)}`\n\n/** The message every read rejects with while the client has no configuration at all. */\nexport const notConfiguredMessage = (caller: string, integration: Integration): string =>\n `${PREFIX} the client is not configured: ${caller} was called before configure() ever ran, so neither backendUrl nor projectId is known and no manifest can be requested.\\n\\n${howToConfigure(integration)}`\n","import type { Integration } from \"./errors\"\nimport type { Identities, Manifest, OrchestratorConfig, WebpackContainer } from \"./types\"\n\nexport interface OrchestratorState {\n config: OrchestratorConfig | null\n manifestPromise: Promise<Manifest> | null\n identities: Identities | null\n /** Set by the framework adapters as they load, so an error prints the snippet of their own API. */\n integration: Integration\n // The webpack remote loader's state, below. Optional because a slot created by an older copy of\n // this package on the same page has none of it: each field is filled in on first use.\n /** Settled by the first `configure()`, so a remote requested earlier can wait for it. */\n configured?: { promise: Promise<void>; resolve: () => void }\n /** One script load per remote entry URL, shared by every caller asking for it. */\n remoteEntries?: Map<string, Promise<void>>\n /** One guarded proxy per container, so the guard holds however many times it is resolved. */\n containers?: WeakMap<WebpackContainer, WebpackContainer>\n}\n\n/**\n * The state lives on `globalThis` under this key, not in a module scope variable.\n *\n * A host can end up with two copies of this package loaded at once: the app imports the ESM build\n * while something else pulls the CJS one, or the bundler config and the app resolve to different\n * chunks. Two module scopes would mean two configurations and two manifest requests, which is\n * exactly what the contract forbids. One well known global slot makes the singleton real.\n */\nexport const STATE_KEY = \"__mfe_orchestrator_client__\"\n\nconst globalSlot = globalThis as typeof globalThis & Record<typeof STATE_KEY, OrchestratorState | undefined>\n\nexport const getState = (): OrchestratorState => {\n let state = globalSlot[STATE_KEY]\n if (!state) {\n state = { config: null, manifestPromise: null, identities: null, integration: \"core\" }\n globalSlot[STATE_KEY] = state\n }\n return state\n}\n","import type { Identities } from \"./types\"\n\nexport const SESSION_ID_KEY = \"mfe-orchestrator.sessionId\"\nexport const DEVICE_ID_KEY = \"mfe-orchestrator.deviceId\"\n\nconst PROBE_KEY = \"mfe-orchestrator.probe\"\n\ntype StorageKind = \"local\" | \"session\"\n\n/**\n * Ids minted while storage was unusable. They live for the lifetime of the page so that, even\n * without storage, every request of this page load carries one stable pair of ids.\n */\nconst inMemoryIds = new Map<string, string>()\n\nconst uuidFromRandomBytes = (bytes: Uint8Array): string => {\n bytes[6] = (bytes[6] & 0x0f) | 0x40\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n const hex: string[] = []\n for (const byte of bytes) {\n hex.push(byte.toString(16).padStart(2, \"0\"))\n }\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`\n}\n\n/**\n * A v4 UUID. `crypto.randomUUID` is the intended path; the two fallbacks only exist so that a page\n * served over plain http, or an exotic runtime, still gets an id instead of an exception.\n */\nexport const newId = (): string => {\n const cryptoApi = globalThis.crypto\n try {\n if (typeof cryptoApi?.randomUUID === \"function\") {\n return cryptoApi.randomUUID()\n }\n if (typeof cryptoApi?.getRandomValues === \"function\") {\n return uuidFromRandomBytes(cryptoApi.getRandomValues(new Uint8Array(16)))\n }\n } catch {\n // fall through to the non cryptographic fallback\n }\n const bytes = new Uint8Array(16)\n for (let index = 0; index < bytes.length; index++) {\n bytes[index] = Math.floor(Math.random() * 256)\n }\n return uuidFromRandomBytes(bytes)\n}\n\n/**\n * The requested storage, or `null` when it is missing or unusable.\n *\n * Both the property access and the write can throw: Safari in private mode exposes the object and\n * then refuses `setItem`, some hardened browsers throw a SecurityError on the access itself. The\n * write probe is the only reliable way to tell a usable storage from a decorative one.\n */\nconst openStorage = (kind: StorageKind): Storage | null => {\n try {\n const storage = kind === \"local\" ? globalThis.localStorage : globalThis.sessionStorage\n if (!storage) {\n return null\n }\n storage.setItem(PROBE_KEY, \"1\")\n storage.removeItem(PROBE_KEY)\n return storage\n } catch {\n return null\n }\n}\n\n/**\n * The id under `key`, read from storage and created on first use. Falls back to an id kept in\n * memory when storage cannot be used, so this never throws out of the SDK.\n */\nconst persistentId = (kind: StorageKind, key: string): string => {\n const storage = openStorage(kind)\n if (storage) {\n try {\n const stored = storage.getItem(key)\n if (stored) {\n return stored\n }\n const created = newId()\n storage.setItem(key, created)\n return created\n } catch {\n // storage passed the probe and failed anyway: keep going with an in memory id\n }\n }\n const remembered = inMemoryIds.get(key)\n if (remembered) {\n return remembered\n }\n const created = newId()\n inMemoryIds.set(key, created)\n return created\n}\n\n/** Reads, and creates when needed, the session and device ids. */\nexport const readIdentities = (): Identities => ({\n sessionId: persistentId(\"session\", SESSION_ID_KEY),\n deviceId: persistentId(\"local\", DEVICE_ID_KEY)\n})\n","import { notConfiguredMessage, PREFIX } from \"./errors\"\nimport { manifest, remoteUrl } from \"./index\"\nimport { getState, type OrchestratorState } from \"./state\"\nimport type { WebpackContainer } from \"./types\"\n\n/**\n * The global the webpack config reaches the client through.\n *\n * A `promise` remote of ModuleFederationPlugin is an expression pasted verbatim into the host\n * bundle, outside of any module, so it cannot import this package: a bare `import()` there reaches\n * the browser untouched and fails to resolve. A well known global is the one thing such an\n * expression can always read, hence `promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote(…)`.\n */\nexport const GLOBAL_NAMESPACE = \"__MFE_ORCHESTRATOR__\"\n\n/** What the global namespace carries. Only ever extended, so an older config keeps working. */\nexport interface OrchestratorGlobal {\n loadWebpackRemote: typeof loadWebpackRemote\n}\n\n/**\n * How long a remote requested before `configure()` waits for it. Long enough for a host that\n * configures after an async step of its own, short enough to turn a configure() that will never run\n * into an error rather than a page that hangs.\n */\nexport const CONFIGURE_TIMEOUT_MS = 10_000\n\nconst globalScope = globalThis as unknown as Record<string, unknown>\n\n/**\n * Puts the loader on the global namespace. Run when the module loads, so a remote requested before\n * `configure()` finds it, and again by `configure()`, in case a bundler dropped the top level call\n * believing the module free of side effects. The first copy of the package to publish keeps the\n * slot: every copy reads the same global state, so they are interchangeable.\n */\nexport const publishGlobal = (): void => {\n const existing = globalScope[GLOBAL_NAMESPACE] as Partial<OrchestratorGlobal> | undefined\n const namespace: Partial<OrchestratorGlobal> = existing ?? {}\n if (typeof namespace.loadWebpackRemote !== \"function\") {\n namespace.loadWebpackRemote = loadWebpackRemote\n }\n globalScope[GLOBAL_NAMESPACE] = namespace\n}\n\nconst configuredSignal = (state: OrchestratorState): NonNullable<OrchestratorState[\"configured\"]> => {\n if (!state.configured) {\n let resolve = (): void => {}\n const promise = new Promise<void>(settle => {\n resolve = settle\n })\n state.configured = { promise, resolve }\n }\n return state.configured\n}\n\n/** Called by `configure()` once it stored a configuration: releases every remote waiting for it. */\nexport const markConfigured = (): void => {\n configuredSignal(getState()).resolve()\n}\n\n/**\n * Resolves once the client is configured. Waiting rather than rejecting right away is what lets a\n * host configure after a step of its own, but only for so long: a remote imported by the very chunk\n * that calls `configure()` makes webpack load the remote before that chunk ever runs, and that\n * would otherwise hang the page forever.\n */\nconst whenConfigured = (caller: string): Promise<void> => {\n const state = getState()\n if (state.config) {\n return Promise.resolve()\n }\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(\n new Error(\n `${notConfiguredMessage(caller, state.integration)}\\n\\nThe remote waited ${CONFIGURE_TIMEOUT_MS / 1000} seconds for it. With webpack, call configure() in the entry file and load the rest of the app with import(\"./bootstrap\") after it: a remote imported by the chunk that calls configure() is loaded before that chunk runs, so it can never see the configuration.`\n )\n )\n }, CONFIGURE_TIMEOUT_MS)\n configuredSignal(state).promise.then(() => {\n clearTimeout(timer)\n resolve()\n })\n })\n}\n\n/**\n * Injects the remote entry script once per URL. Concurrent and later callers share the same load. A\n * failed load is forgotten, like a failed manifest, so the next caller tries again instead of\n * inheriting a rejection for the rest of the page load.\n */\nconst loadRemoteEntry = (url: string, slug: string): Promise<void> => {\n const state = getState()\n state.remoteEntries ??= new Map()\n const entries = state.remoteEntries\n const known = entries.get(url)\n if (known) {\n return known\n }\n const load = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(new Error(`${PREFIX} loadWebpackRemote(\"${slug}\") needs a browser document to load ${url} into, and there is none here.`))\n return\n }\n const script = document.createElement(\"script\")\n script.src = url\n script.async = true\n script.onload = () => resolve()\n script.onerror = () => {\n script.remove()\n reject(\n new Error(\n `${PREFIX} the remote entry of \"${slug}\" failed to load from ${url}. The browser gives no reason for a failed script, so open the URL in a tab or look at the network panel: a 404 means the served version has no file at that path, a blocked request usually means a Content-Security-Policy (script-src) or a mixed content rule.`\n )\n )\n }\n document.head.appendChild(script)\n })\n entries.set(url, load)\n load.catch(() => {\n if (entries.get(url) === load) {\n entries.delete(url)\n }\n })\n return load\n}\n\nconst isContainer = (value: unknown): value is WebpackContainer =>\n typeof value === \"object\" && value !== null && typeof (value as WebpackContainer).get === \"function\" && typeof (value as WebpackContainer).init === \"function\"\n\n/** Global names holding something shaped like a container, to point at the name the remote really uses. */\nconst containerNames = (): string[] => {\n const names: string[] = []\n for (const key of Object.keys(globalScope)) {\n try {\n if (isContainer(globalScope[key])) {\n names.push(`\"${key}\"`)\n }\n } catch {\n // A getter on the global that throws is simply not a container.\n }\n }\n return names\n}\n\nconst missingContainerMessage = (slug: string, scope: string, url: string): string => {\n const found = containerNames()\n return `${PREFIX} the remote entry of \"${slug}\" loaded from ${url}, but globalThis[\"${scope}\"] is not a webpack container. The scope must be the name the remote passes to its own ModuleFederationPlugin, and the remote must keep its default library type (\"var\"). ${\n found.length > 0 ? `Containers on this page: ${found.join(\", \")}.` : \"No container is defined on this page at all.\"\n } A remote built with Vite is an ES module, not a webpack container, and cannot be loaded this way.`\n}\n\n/**\n * A `{ get, init }` passthrough that ignores every `init` after the first. A container may be\n * initialized only once: two hosts, or two remotes sharing a third, would otherwise both init it and\n * webpack throws on the second share scope. The later calls get the result of the first.\n */\nconst guarded = (container: WebpackContainer): WebpackContainer => {\n const state = getState()\n state.containers ??= new WeakMap()\n const known = state.containers.get(container)\n if (known) {\n return known\n }\n let initialized: { result: unknown } | null = null\n const proxy: WebpackContainer = {\n get: module => container.get(module),\n init: (shareScope, initScope) => {\n if (!initialized) {\n initialized = { result: container.init(shareScope, initScope) }\n }\n return initialized.result\n }\n }\n state.containers.set(container, proxy)\n return proxy\n}\n\n/**\n * What a webpack `promise` remote must resolve to: the container of the microfrontend, at the\n * version the backend serves this page.\n *\n * It resolves the URL with `remoteUrl(slug)`, injects that remote entry script once per URL, reads\n * the container off `globalThis[scope]` and returns a `{ get, init }` proxy whose `init` runs once.\n * Requested before `configure()`, it waits for it, up to `CONFIGURE_TIMEOUT_MS`.\n *\n * `scope` is the remote's own ModuleFederationPlugin `name`. Left out, it is the `nameToIntegrate`\n * of the microfrontend in the manifest, which is the name the console generates for it.\n *\n * Meant for the webpack config, through the global namespace, not for application code:\n *\n * remotes: {\n * checkoutnew: \"promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote('checkout-new', 'checkoutnew')\"\n * }\n */\nexport const loadWebpackRemote = async (slug: string, scope?: string): Promise<WebpackContainer> => {\n const caller = `loadWebpackRemote(\"${slug}\")`\n await whenConfigured(caller)\n const url = await remoteUrl(slug)\n const name = scope || (await manifest()).microfrontends.find(microfrontend => microfrontend.slug === slug)?.nameToIntegrate\n if (!name) {\n throw new Error(\n `${PREFIX} ${caller} has no scope: none was passed and the manifest gives no nameToIntegrate for \"${slug}\". Pass the name the remote gives its ModuleFederationPlugin as the second argument.`\n )\n }\n await loadRemoteEntry(url, slug)\n const container = globalScope[name]\n if (!isContainer(container)) {\n throw new Error(missingContainerMessage(slug, name, url))\n }\n return guarded(container)\n}\n\n// On load, not only in configure(): a webpack remote requested before configure() ran must find the\n// loader on the global namespace, and then waits for the configuration. It lives here rather than in\n// index.ts because the two modules import each other, and only this one is sure to have evaluated its\n// own exports by the time this line runs, whichever of the two is loaded first.\npublishGlobal()\n","import { diagnoseConfig, type Integration, invalidConfigMessage, noConfigMessage, notConfiguredMessage, PREFIX } from \"./errors\"\nimport { getState } from \"./state\"\nimport { readIdentities } from \"./storage\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\nimport { markConfigured, publishGlobal } from \"./webpack\"\n\nexport type { ConfigProblem, Integration } from \"./errors\"\nexport type { GlobalVariable, Identities, Manifest, Microfrontend, OrchestratorConfig, WebpackContainer } from \"./types\"\nexport { CONFIGURE_TIMEOUT_MS, GLOBAL_NAMESPACE, loadWebpackRemote, type OrchestratorGlobal } from \"./webpack\"\n\nconst withoutTrailingSlash = (value: string): string => value.replace(/\\/+$/, \"\")\n\nconst resolveUserId = async (userId: OrchestratorConfig[\"userId\"]): Promise<string | undefined> => {\n const value = typeof userId === \"function\" ? await userId() : userId\n return value === undefined || value === null || value === \"\" ? undefined : String(value)\n}\n\n/** Everything but the identity: the part of the configuration that is fixed for a page load. */\nconst sameTarget = (left: OrchestratorConfig, right: OrchestratorConfig): boolean =>\n left.backendUrl === right.backendUrl && left.projectId === right.projectId && left.environment === right.environment\n\nconst sameConfig = (left: OrchestratorConfig, right: OrchestratorConfig): boolean => sameTarget(left, right) && left.userId === right.userId\n\n/**\n * Whether replacing the identity would change nothing. Two getters are never considered equal, even the\n * same one twice: what a function returns is exactly what this side cannot know, so a host handing one\n * over is taken at its word and the manifest is re-fetched.\n */\nconst sameUserId = (left: OrchestratorConfig[\"userId\"], right: OrchestratorConfig[\"userId\"]): boolean => typeof left !== \"function\" && typeof right !== \"function\" && left === right\n\n/**\n * Rejects a configuration the client could not use, with a message that names the option, shows what\n * actually arrived and prints the call to write. environment is deliberately not required: without\n * it the backend resolves it from the domain. It is still checked for type, because a non string\n * there would silently end up percent encoded into the path.\n */\nconst requireConfig = (config: OrchestratorConfig, integration: Integration): void => {\n if (typeof config !== \"object\" || config === null) {\n throw new Error(noConfigMessage(config, integration))\n }\n const problems = diagnoseConfig(config)\n if (problems.length > 0) {\n throw new Error(invalidConfigMessage(problems, integration))\n }\n if (config.environment !== undefined && config.environment !== null && typeof config.environment !== \"string\") {\n throw new Error(\n `${PREFIX} configure() received environment as a ${typeof config.environment}, not a string. Pass the environment slug as it appears in the console, ex. \"DEV\", or leave it out to let the backend resolve it from the domain of this page.`\n )\n }\n}\n\n/** Notices about a stored configuration that works but probably does not do what the host meant. */\nconst warnAboutConfig = (config: OrchestratorConfig): void => {\n if (typeof config.environment === \"string\" && config.environment.trim() === \"\") {\n console.warn(\n `${PREFIX} configure() received an empty environment, so the client falls back to the auto routes and the backend resolves the environment from the domain of this page. Remove the option if that is what you want, or check the variable that feeds it.`\n )\n }\n}\n\n/**\n * Two shapes, one per route family. With an explicit environment the slug is the last segment; with\n * no environment the \"auto\" segment takes its place before the project id and the backend resolves\n * the environment from the domain the request comes from.\n */\nconst manifestPath = (config: OrchestratorConfig): string => {\n const projectId = encodeURIComponent(config.projectId)\n return config.environment ? `/serve/all/${projectId}/${encodeURIComponent(config.environment)}` : `/serve/all/auto/${projectId}`\n}\n\nconst manifestUrl = async (config: OrchestratorConfig): Promise<string> => {\n const { sessionId, deviceId } = identities()\n const query = new URLSearchParams({ mfeSessionId: sessionId, mfeDeviceId: deviceId })\n // Resolved as late as possible: the host may only know the user after its own auth round trip.\n const userId = await resolveUserId(config.userId)\n if (userId) {\n query.set(\"mfeUserId\", userId)\n }\n return `${withoutTrailingSlash(config.backendUrl)}${manifestPath(config)}?${query.toString()}`\n}\n\n/**\n * What a status usually means on this route. The backend answers the same 404 for an unknown project\n * and for an unknown environment, and the two are indistinguishable from here, so both are named.\n */\nconst statusHint = (status: number, config: OrchestratorConfig): string => {\n if (status === 404) {\n const environment = config.environment\n ? `the environment \"${config.environment}\" does not exist in it`\n : \"no environment of that project declares the domain this page is served on, which is what the auto route resolves on\"\n return `\\n\\nA 404 on this route means the backend did not find what the URL names: either the project id \"${config.projectId}\" is not a project of this console, or ${environment}. Check both in the console, and check that backendUrl points at the console API of the same instance.`\n }\n if (status === 401 || status === 403) {\n return `\\n\\nThe console refused the request. Check that the project id \"${config.projectId}\" belongs to the instance backendUrl points at, and that this domain is allowed to read its manifest.`\n }\n return \"\"\n}\n\nconst fetchManifest = async (config: OrchestratorConfig): Promise<Manifest> => {\n const url = await manifestUrl(config)\n // No retry in v1: whatever fetch throws travels straight to the caller.\n const response = await fetch(url, { headers: { accept: \"application/json\" } })\n if (!response.ok) {\n throw new Error(`${PREFIX} the manifest request failed with ${response.status} ${response.statusText}. GET ${url}${statusHint(response.status, config)}`)\n }\n const payload = (await response.json()) as Partial<Manifest> | null\n return {\n globalVariables: payload?.globalVariables ?? [],\n microfrontends: payload?.microfrontends ?? []\n }\n}\n\n/**\n * Hands the client its configuration. Call it once, synchronously, before any remote is imported.\n *\n * `backendUrl` and `projectId` are required. `environment` is not: omitting it makes the client use\n * the \"auto\" routes, where the backend resolves the environment from the domain of the host page.\n *\n * Idempotent: calling it again with the same options is a no op, so a framework provider may safely\n * call it on every render. A second call with different options is ignored, with a warning, because\n * the manifest of this page load may already be in flight or resolved. The user is the exception, and\n * it changes through `setUserId()`, not through a second call here.\n *\n * It also publishes `globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote`, which a webpack config\n * reaches the client through, and releases every webpack remote that was requested before it ran.\n */\nexport const configure = (config: OrchestratorConfig): void => {\n const state = getState()\n publishGlobal()\n requireConfig(config, state.integration)\n const current = state.config\n if (current) {\n if (!sameConfig(current, config)) {\n console.warn(\n sameTarget(current, config)\n ? `${PREFIX} configure() was called again with a different userId. The configuration is fixed for this page load, so this one is ignored: call setUserId() instead, which is the supported way to change the user mid session and also drops the memoized manifest, so the next read is decided on the new identity.`\n : `${PREFIX} configure() was called again with a different configuration. The first one is kept: ${JSON.stringify({ backendUrl: current.backendUrl, projectId: current.projectId, environment: current.environment })}.`\n )\n }\n return\n }\n state.config = { ...config }\n warnAboutConfig(config)\n markConfigured()\n}\n\n/**\n * Replaces the identity the backend decides a user based canary on, after the client was configured.\n *\n * `configure()` is deliberately once only, and this is the one option that legitimately changes while\n * the page is alive: a login, a logout, an account switch. So it gets its own setter, and that setter\n * does what `configure()` must not — it drops the memoized manifest, so the next `manifest()`,\n * `remoteUrl()` or `globalVariables()` asks the backend again and is answered for the new user.\n *\n * Pass `undefined` on logout: the next request then carries no `mfeUserId` at all, which is what makes\n * the backend hand out the stable version again.\n *\n * What this does NOT do is reload the remotes already imported. The federation runtime keeps the\n * container it has, so a microfrontend already on the page stays on the version drawn for the previous\n * user, and only remotes resolved after this call see the new one. When the whole page must be\n * consistent, follow the identity change with a reload; when the host mounts its remotes behind its own\n * auth guard, calling this before the guard opens is enough.\n *\n * Setting the same plain value again is a no op, so an auth store may call it on every emission without\n * costing a request. A getter is always taken as a change, since what it returns is precisely what this\n * side cannot know.\n *\n * A request already in flight is not cancelled: whoever is awaiting it still receives the manifest of\n * the previous identity. Only the memo is dropped.\n */\nexport const setUserId = (userId: OrchestratorConfig[\"userId\"]): void => {\n const state = getState()\n const current = state.config\n if (!current) {\n throw new Error(notConfiguredMessage(\"setUserId()\", state.integration))\n }\n if (sameUserId(current.userId, userId)) {\n return\n }\n state.config = { ...current, userId }\n state.manifestPromise = null\n}\n\n/**\n * @internal Lets a framework adapter say which package the host is really using, so a configuration\n * error prints the snippet of that API instead of the bare `configure()` one. Idempotent, and never\n * needed by an application: the adapters call it as they load.\n */\nexport const registerIntegration = (integration: Integration): void => {\n getState().integration = integration\n}\n\n/**\n * The whole manifest of the environment, fetched once per page load and memoized as a promise, so\n * that concurrent callers share the single request in flight.\n *\n * A successful result is memoized for good. A failed attempt is not: the memo is dropped when the\n * shared attempt settles as rejected, so the next caller starts a fresh request. That is not a retry\n * — nothing here loops or backs off — it only means one flaky lookup at boot does not condemn the\n * page to reject every `remoteUrl()` until a full reload.\n */\nconst loadManifest = (caller: string): Promise<Manifest> => {\n const state = getState()\n const config = state.config\n if (!config) {\n // Not memoized: the host may still configure the client and try again.\n return Promise.reject(new Error(notConfiguredMessage(caller, state.integration)))\n }\n if (!state.manifestPromise) {\n // Assigned before the first await inside fetchManifest, which is what makes N concurrent\n // callers collapse onto one request.\n const attempt = fetchManifest(config)\n state.manifestPromise = attempt\n // Cleared once, when the shared attempt settles, not in each caller's own catch: every\n // caller already waiting on this attempt still gets its rejection. The identity check keeps\n // a late failure from evicting a newer attempt.\n attempt.catch(() => {\n if (state.manifestPromise === attempt) {\n state.manifestPromise = null\n }\n })\n }\n return state.manifestPromise\n}\n\n/** The whole manifest of the environment. See `loadManifest` for the memoization contract. */\nexport const manifest = (): Promise<Manifest> => loadManifest(\"manifest()\")\n\n/**\n * The ready to use, version pinned URL of a remote. Awaits the manifest internally.\n *\n * The returned URL is used verbatim: the host never parses the version out of it and never strips\n * the `_v/<version>/` segment, or a classic script would load its chunks off another version.\n */\nexport const remoteUrl = async (slug: string): Promise<string> => {\n const { microfrontends } = await loadManifest(`remoteUrl(\"${slug}\")`)\n const found = microfrontends.find(microfrontend => microfrontend.slug === slug)\n if (!found) {\n const available = microfrontends.map(microfrontend => `\"${microfrontend.slug}\"`).join(\", \")\n const environment = getState().config?.environment\n // With no configured environment the host cannot name the one it was served: only the backend knows.\n const where = environment ? `environment \"${environment}\"` : \"the environment resolved from this domain\"\n throw new Error(`${PREFIX} unknown microfrontend slug \"${slug}\". Available in ${where}: ${available || \"none, this environment serves no microfrontend\"}.`)\n }\n if (!found.url) {\n throw new Error(`${PREFIX} the microfrontend \"${slug}\" is in the manifest but carries no url. Check its deployment in the console.`)\n }\n return found.url\n}\n\n/** The global variables of the environment, as a plain object. */\nexport const globalVariables = async (): Promise<Record<string, string>> => {\n const { globalVariables: variables } = await loadManifest(\"globalVariables()\")\n const result: Record<string, string> = {}\n for (const variable of variables) {\n if (variable && typeof variable.key === \"string\") {\n result[variable.key] = variable.value\n }\n }\n return result\n}\n\n/**\n * The session and device ids of this page, exposed for telemetry and debugging. Created on first\n * use and stable for the lifetime of the page, whether or not storage is available.\n */\nexport const identities = (): Identities => {\n const state = getState()\n if (!state.identities) {\n state.identities = readIdentities()\n }\n return state.identities\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -68,6 +68,54 @@ interface Identities {
68
68
  sessionId: string;
69
69
  deviceId: string;
70
70
  }
71
+ /**
72
+ * A webpack module federation container, the object a remote entry script assigns to its global
73
+ * name, and what a webpack `promise` remote has to resolve to.
74
+ */
75
+ interface WebpackContainer {
76
+ /** Resolves to the factory of an exposed module, ex. `get("./Button")`. */
77
+ get(module: string): Promise<() => unknown>;
78
+ /** Hands the container the host's share scope. Called by the host's webpack runtime. */
79
+ init(shareScope: unknown, initScope?: unknown): unknown;
80
+ }
81
+
82
+ /**
83
+ * The global the webpack config reaches the client through.
84
+ *
85
+ * A `promise` remote of ModuleFederationPlugin is an expression pasted verbatim into the host
86
+ * bundle, outside of any module, so it cannot import this package: a bare `import()` there reaches
87
+ * the browser untouched and fails to resolve. A well known global is the one thing such an
88
+ * expression can always read, hence `promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote(…)`.
89
+ */
90
+ declare const GLOBAL_NAMESPACE = "__MFE_ORCHESTRATOR__";
91
+ /** What the global namespace carries. Only ever extended, so an older config keeps working. */
92
+ interface OrchestratorGlobal {
93
+ loadWebpackRemote: typeof loadWebpackRemote;
94
+ }
95
+ /**
96
+ * How long a remote requested before `configure()` waits for it. Long enough for a host that
97
+ * configures after an async step of its own, short enough to turn a configure() that will never run
98
+ * into an error rather than a page that hangs.
99
+ */
100
+ declare const CONFIGURE_TIMEOUT_MS = 10000;
101
+ /**
102
+ * What a webpack `promise` remote must resolve to: the container of the microfrontend, at the
103
+ * version the backend serves this page.
104
+ *
105
+ * It resolves the URL with `remoteUrl(slug)`, injects that remote entry script once per URL, reads
106
+ * the container off `globalThis[scope]` and returns a `{ get, init }` proxy whose `init` runs once.
107
+ * Requested before `configure()`, it waits for it, up to `CONFIGURE_TIMEOUT_MS`.
108
+ *
109
+ * `scope` is the remote's own ModuleFederationPlugin `name`. Left out, it is the `nameToIntegrate`
110
+ * of the microfrontend in the manifest, which is the name the console generates for it.
111
+ *
112
+ * Meant for the webpack config, through the global namespace, not for application code:
113
+ *
114
+ * remotes: {
115
+ * checkoutnew: "promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote('checkout-new', 'checkoutnew')"
116
+ * }
117
+ */
118
+ declare const loadWebpackRemote: (slug: string, scope?: string) => Promise<WebpackContainer>;
71
119
 
72
120
  /**
73
121
  * Hands the client its configuration. Call it once, synchronously, before any remote is imported.
@@ -79,6 +127,9 @@ interface Identities {
79
127
  * call it on every render. A second call with different options is ignored, with a warning, because
80
128
  * the manifest of this page load may already be in flight or resolved. The user is the exception, and
81
129
  * it changes through `setUserId()`, not through a second call here.
130
+ *
131
+ * It also publishes `globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote`, which a webpack config
132
+ * reaches the client through, and releases every webpack remote that was requested before it ran.
82
133
  */
83
134
  declare const configure: (config: OrchestratorConfig) => void;
84
135
  /**
@@ -129,4 +180,4 @@ declare const globalVariables: () => Promise<Record<string, string>>;
129
180
  */
130
181
  declare const identities: () => Identities;
131
182
 
132
- export { type ConfigProblem, type GlobalVariable, type Identities, type Integration, type Manifest, type Microfrontend, type OrchestratorConfig, configure, globalVariables, identities, manifest, registerIntegration, remoteUrl, setUserId };
183
+ export { CONFIGURE_TIMEOUT_MS, type ConfigProblem, GLOBAL_NAMESPACE, type GlobalVariable, type Identities, type Integration, type Manifest, type Microfrontend, type OrchestratorConfig, type OrchestratorGlobal, type WebpackContainer, configure, globalVariables, identities, loadWebpackRemote, manifest, registerIntegration, remoteUrl, setUserId };
package/dist/index.d.ts CHANGED
@@ -68,6 +68,54 @@ interface Identities {
68
68
  sessionId: string;
69
69
  deviceId: string;
70
70
  }
71
+ /**
72
+ * A webpack module federation container, the object a remote entry script assigns to its global
73
+ * name, and what a webpack `promise` remote has to resolve to.
74
+ */
75
+ interface WebpackContainer {
76
+ /** Resolves to the factory of an exposed module, ex. `get("./Button")`. */
77
+ get(module: string): Promise<() => unknown>;
78
+ /** Hands the container the host's share scope. Called by the host's webpack runtime. */
79
+ init(shareScope: unknown, initScope?: unknown): unknown;
80
+ }
81
+
82
+ /**
83
+ * The global the webpack config reaches the client through.
84
+ *
85
+ * A `promise` remote of ModuleFederationPlugin is an expression pasted verbatim into the host
86
+ * bundle, outside of any module, so it cannot import this package: a bare `import()` there reaches
87
+ * the browser untouched and fails to resolve. A well known global is the one thing such an
88
+ * expression can always read, hence `promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote(…)`.
89
+ */
90
+ declare const GLOBAL_NAMESPACE = "__MFE_ORCHESTRATOR__";
91
+ /** What the global namespace carries. Only ever extended, so an older config keeps working. */
92
+ interface OrchestratorGlobal {
93
+ loadWebpackRemote: typeof loadWebpackRemote;
94
+ }
95
+ /**
96
+ * How long a remote requested before `configure()` waits for it. Long enough for a host that
97
+ * configures after an async step of its own, short enough to turn a configure() that will never run
98
+ * into an error rather than a page that hangs.
99
+ */
100
+ declare const CONFIGURE_TIMEOUT_MS = 10000;
101
+ /**
102
+ * What a webpack `promise` remote must resolve to: the container of the microfrontend, at the
103
+ * version the backend serves this page.
104
+ *
105
+ * It resolves the URL with `remoteUrl(slug)`, injects that remote entry script once per URL, reads
106
+ * the container off `globalThis[scope]` and returns a `{ get, init }` proxy whose `init` runs once.
107
+ * Requested before `configure()`, it waits for it, up to `CONFIGURE_TIMEOUT_MS`.
108
+ *
109
+ * `scope` is the remote's own ModuleFederationPlugin `name`. Left out, it is the `nameToIntegrate`
110
+ * of the microfrontend in the manifest, which is the name the console generates for it.
111
+ *
112
+ * Meant for the webpack config, through the global namespace, not for application code:
113
+ *
114
+ * remotes: {
115
+ * checkoutnew: "promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote('checkout-new', 'checkoutnew')"
116
+ * }
117
+ */
118
+ declare const loadWebpackRemote: (slug: string, scope?: string) => Promise<WebpackContainer>;
71
119
 
72
120
  /**
73
121
  * Hands the client its configuration. Call it once, synchronously, before any remote is imported.
@@ -79,6 +127,9 @@ interface Identities {
79
127
  * call it on every render. A second call with different options is ignored, with a warning, because
80
128
  * the manifest of this page load may already be in flight or resolved. The user is the exception, and
81
129
  * it changes through `setUserId()`, not through a second call here.
130
+ *
131
+ * It also publishes `globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote`, which a webpack config
132
+ * reaches the client through, and releases every webpack remote that was requested before it ran.
82
133
  */
83
134
  declare const configure: (config: OrchestratorConfig) => void;
84
135
  /**
@@ -129,4 +180,4 @@ declare const globalVariables: () => Promise<Record<string, string>>;
129
180
  */
130
181
  declare const identities: () => Identities;
131
182
 
132
- export { type ConfigProblem, type GlobalVariable, type Identities, type Integration, type Manifest, type Microfrontend, type OrchestratorConfig, configure, globalVariables, identities, manifest, registerIntegration, remoteUrl, setUserId };
183
+ export { CONFIGURE_TIMEOUT_MS, type ConfigProblem, GLOBAL_NAMESPACE, type GlobalVariable, type Identities, type Integration, type Manifest, type Microfrontend, type OrchestratorConfig, type OrchestratorGlobal, type WebpackContainer, configure, globalVariables, identities, loadWebpackRemote, manifest, registerIntegration, remoteUrl, setUserId };
package/dist/index.js CHANGED
@@ -225,6 +225,144 @@ var readIdentities = () => ({
225
225
  deviceId: persistentId("local", DEVICE_ID_KEY)
226
226
  });
227
227
 
228
+ // src/webpack.ts
229
+ var GLOBAL_NAMESPACE = "__MFE_ORCHESTRATOR__";
230
+ var CONFIGURE_TIMEOUT_MS = 1e4;
231
+ var globalScope = globalThis;
232
+ var publishGlobal = () => {
233
+ const existing = globalScope[GLOBAL_NAMESPACE];
234
+ const namespace = existing ?? {};
235
+ if (typeof namespace.loadWebpackRemote !== "function") {
236
+ namespace.loadWebpackRemote = loadWebpackRemote;
237
+ }
238
+ globalScope[GLOBAL_NAMESPACE] = namespace;
239
+ };
240
+ var configuredSignal = (state) => {
241
+ if (!state.configured) {
242
+ let resolve = () => {
243
+ };
244
+ const promise = new Promise((settle) => {
245
+ resolve = settle;
246
+ });
247
+ state.configured = { promise, resolve };
248
+ }
249
+ return state.configured;
250
+ };
251
+ var markConfigured = () => {
252
+ configuredSignal(getState()).resolve();
253
+ };
254
+ var whenConfigured = (caller) => {
255
+ const state = getState();
256
+ if (state.config) {
257
+ return Promise.resolve();
258
+ }
259
+ return new Promise((resolve, reject) => {
260
+ const timer = setTimeout(() => {
261
+ reject(
262
+ new Error(
263
+ `${notConfiguredMessage(caller, state.integration)}
264
+
265
+ The remote waited ${CONFIGURE_TIMEOUT_MS / 1e3} seconds for it. With webpack, call configure() in the entry file and load the rest of the app with import("./bootstrap") after it: a remote imported by the chunk that calls configure() is loaded before that chunk runs, so it can never see the configuration.`
266
+ )
267
+ );
268
+ }, CONFIGURE_TIMEOUT_MS);
269
+ configuredSignal(state).promise.then(() => {
270
+ clearTimeout(timer);
271
+ resolve();
272
+ });
273
+ });
274
+ };
275
+ var loadRemoteEntry = (url, slug) => {
276
+ const state = getState();
277
+ state.remoteEntries ??= /* @__PURE__ */ new Map();
278
+ const entries = state.remoteEntries;
279
+ const known = entries.get(url);
280
+ if (known) {
281
+ return known;
282
+ }
283
+ const load = new Promise((resolve, reject) => {
284
+ if (typeof document === "undefined") {
285
+ reject(new Error(`${PREFIX} loadWebpackRemote("${slug}") needs a browser document to load ${url} into, and there is none here.`));
286
+ return;
287
+ }
288
+ const script = document.createElement("script");
289
+ script.src = url;
290
+ script.async = true;
291
+ script.onload = () => resolve();
292
+ script.onerror = () => {
293
+ script.remove();
294
+ reject(
295
+ new Error(
296
+ `${PREFIX} the remote entry of "${slug}" failed to load from ${url}. The browser gives no reason for a failed script, so open the URL in a tab or look at the network panel: a 404 means the served version has no file at that path, a blocked request usually means a Content-Security-Policy (script-src) or a mixed content rule.`
297
+ )
298
+ );
299
+ };
300
+ document.head.appendChild(script);
301
+ });
302
+ entries.set(url, load);
303
+ load.catch(() => {
304
+ if (entries.get(url) === load) {
305
+ entries.delete(url);
306
+ }
307
+ });
308
+ return load;
309
+ };
310
+ var isContainer = (value) => typeof value === "object" && value !== null && typeof value.get === "function" && typeof value.init === "function";
311
+ var containerNames = () => {
312
+ const names = [];
313
+ for (const key of Object.keys(globalScope)) {
314
+ try {
315
+ if (isContainer(globalScope[key])) {
316
+ names.push(`"${key}"`);
317
+ }
318
+ } catch {
319
+ }
320
+ }
321
+ return names;
322
+ };
323
+ var missingContainerMessage = (slug, scope, url) => {
324
+ const found = containerNames();
325
+ return `${PREFIX} the remote entry of "${slug}" loaded from ${url}, but globalThis["${scope}"] is not a webpack container. The scope must be the name the remote passes to its own ModuleFederationPlugin, and the remote must keep its default library type ("var"). ${found.length > 0 ? `Containers on this page: ${found.join(", ")}.` : "No container is defined on this page at all."} A remote built with Vite is an ES module, not a webpack container, and cannot be loaded this way.`;
326
+ };
327
+ var guarded = (container) => {
328
+ const state = getState();
329
+ state.containers ??= /* @__PURE__ */ new WeakMap();
330
+ const known = state.containers.get(container);
331
+ if (known) {
332
+ return known;
333
+ }
334
+ let initialized = null;
335
+ const proxy = {
336
+ get: (module) => container.get(module),
337
+ init: (shareScope, initScope) => {
338
+ if (!initialized) {
339
+ initialized = { result: container.init(shareScope, initScope) };
340
+ }
341
+ return initialized.result;
342
+ }
343
+ };
344
+ state.containers.set(container, proxy);
345
+ return proxy;
346
+ };
347
+ var loadWebpackRemote = async (slug, scope) => {
348
+ const caller = `loadWebpackRemote("${slug}")`;
349
+ await whenConfigured(caller);
350
+ const url = await remoteUrl(slug);
351
+ const name = scope || (await manifest()).microfrontends.find((microfrontend) => microfrontend.slug === slug)?.nameToIntegrate;
352
+ if (!name) {
353
+ throw new Error(
354
+ `${PREFIX} ${caller} has no scope: none was passed and the manifest gives no nameToIntegrate for "${slug}". Pass the name the remote gives its ModuleFederationPlugin as the second argument.`
355
+ );
356
+ }
357
+ await loadRemoteEntry(url, slug);
358
+ const container = globalScope[name];
359
+ if (!isContainer(container)) {
360
+ throw new Error(missingContainerMessage(slug, name, url));
361
+ }
362
+ return guarded(container);
363
+ };
364
+ publishGlobal();
365
+
228
366
  // src/index.ts
229
367
  var withoutTrailingSlash = (value) => value.replace(/\/+$/, "");
230
368
  var resolveUserId = async (userId) => {
@@ -296,6 +434,7 @@ var fetchManifest = async (config) => {
296
434
  };
297
435
  var configure = (config) => {
298
436
  const state = getState();
437
+ publishGlobal();
299
438
  requireConfig(config, state.integration);
300
439
  const current = state.config;
301
440
  if (current) {
@@ -308,6 +447,7 @@ var configure = (config) => {
308
447
  }
309
448
  state.config = { ...config };
310
449
  warnAboutConfig(config);
450
+ markConfigured();
311
451
  };
312
452
  var setUserId = (userId) => {
313
453
  const state = getState();
@@ -374,6 +514,6 @@ var identities = () => {
374
514
  return state.identities;
375
515
  };
376
516
 
377
- export { configure, globalVariables, identities, manifest, registerIntegration, remoteUrl, setUserId };
517
+ export { CONFIGURE_TIMEOUT_MS, GLOBAL_NAMESPACE, configure, globalVariables, identities, loadWebpackRemote, manifest, registerIntegration, remoteUrl, setUserId };
378
518
  //# sourceMappingURL=index.js.map
379
519
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/state.ts","../src/storage.ts","../src/index.ts"],"names":["created"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Everything the client says when its configuration is wrong or absent.\n *\n * The two required options almost always arrive from build time environment variables, so the\n * failure the host sees is not \"a value is invalid\" but \"nothing reached the bundle\". Messages here\n * are written for that moment: they name the option, show what actually arrived, say where the real\n * value comes from, and print the exact call to write, in the flavour of the package the host uses.\n */\n\nexport const PREFIX = \"[@mfe-orchestrator-hub/client]\"\n\n/** Which package the host went through. Only decides which snippet an error prints. */\nexport type Integration = \"core\" | \"react\" | \"vue\" | \"angular\"\n\n/** The two options without which nothing can be requested. */\nexport type RequiredOption = \"backendUrl\" | \"projectId\"\n\nconst EXAMPLE_BACKEND_URL = \"https://console.mfe-orchestrator.dev/api\"\nconst EXAMPLE_PROJECT_ID = \"6f1b2c3d4e5f6a7b8c9d0e1f\"\n\nconst SNIPPETS: Record<Integration, string> = {\n core: `import { configure } from \"@mfe-orchestrator-hub/client\"\n\nconfigure({\n backendUrl: \"${EXAMPLE_BACKEND_URL}\",\n projectId: \"${EXAMPLE_PROJECT_ID}\"\n})`,\n react: `import { OrchestratorProvider } from \"@mfe-orchestrator-hub/client-react\"\n\n<OrchestratorProvider config={{ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }}>\n <App />\n</OrchestratorProvider>`,\n vue: `import { createOrchestrator } from \"@mfe-orchestrator-hub/client-vue\"\n\napp.use(createOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }))`,\n angular: `import { provideOrchestrator } from \"@mfe-orchestrator-hub/client-angular\"\n\nbootstrapApplication(AppComponent, {\n providers: [provideOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" })]\n})`\n}\n\nconst WHERE: Record<Integration, string> = {\n core: \"Call it once, at the very top of the host entry point, before anything imports a remote.\",\n react: \"Render it above every component that resolves a remote. Better still, call configure() at the very top of the entry point: a bundler may import a remote before React mounts.\",\n vue: \"Install the plugin before mounting the app. Better still, call configure() at the very top of the entry point: a bundler may import a remote before the app is created.\",\n angular: \"Pass it to bootstrapApplication(). Better still, call configure() at the very top of main.ts: a lazily loaded remote must find the client already configured.\"\n}\n\nconst WHAT_IT_IS: Record<RequiredOption, string> = {\n backendUrl: `It is the base URL of the console API, protocol included, ex. \"${EXAMPLE_BACKEND_URL}\". A path on the same origin as the host, ex. \"/api\", works too.`,\n projectId: `It is the id of the project in the console: open the project and copy it from its page, ex. \"${EXAMPLE_PROJECT_ID}\".`\n}\n\n/** The name the value travels under from the bundler config into the bundle, per toolchain. */\nconst BUILD_VARIABLE: Record<RequiredOption, { vite: string; webpack: string }> = {\n backendUrl: { vite: \"VITE_MFE_BACKEND_URL\", webpack: \"MFE_BACKEND_URL\" },\n projectId: { vite: \"VITE_MFE_PROJECT_ID\", webpack: \"MFE_PROJECT_ID\" }\n}\n\n/**\n * What an option that was never substituted into the bundle looks like.\n *\n * The bundler config is named before the .env file on purpose: it is where the console writes both\n * values when it generates the config, so it is where they are missing from when they are missing.\n */\nconst missingEnvHint = (option: RequiredOption): string =>\n `Nothing arrived here at all, which is what a value that never reached the bundle looks like: check ${BUILD_VARIABLE[option].vite} (Vite) or ${BUILD_VARIABLE[option].webpack} (webpack) in the build that produced this bundle. The generated configs carry it in the \"define\" block of vite.config, or in the DefinePlugin of webpack.config, so look there first; declared only in a .env file the build never reads, it looks exactly like this.`\n\n/** Values that mean \"the template was never filled in\". */\nconst PLACEHOLDER = /^(…|\\.{3}|undefined|null|nan|<[^>]*>|\\{\\{[^}]*\\}\\}|\\$\\{[^}]*\\}|your[-_ ]?[a-z]*|x{3,}|change[-_ ]?me|todo|tbd)$/i\n\n/** Long values are cut: an error message is not the place to print a whole JWT. */\nconst quoted = (value: string): string => JSON.stringify(value.length > 120 ? `${value.slice(0, 120)}…` : value)\n\nconst described = (value: unknown): string => {\n if (value === null) {\n return \"null\"\n }\n if (Array.isArray(value)) {\n return \"an array\"\n }\n const type = typeof value\n return type === \"object\" || type === \"function\" ? `a ${type}` : `a ${type} (${String(value)})`\n}\n\n/** Same key modulo case and separators: projectID, project_id, PROJECT-ID all collapse onto projectid. */\nconst normalized = (key: string): string => key.toLowerCase().replace(/[^a-z0-9]/g, \"\")\n\nconst ALIASES: Record<RequiredOption, string[]> = {\n backendUrl: [\"backendurl\", \"backendbaseurl\", \"apiurl\", \"baseurl\", \"consoleurl\", \"url\", \"backend\"],\n projectId: [\"projectid\", \"project\", \"idproject\", \"projectuuid\", \"projectkey\"]\n}\n\n/**\n * The key the host actually wrote, when it looks like a misspelling of the one that is missing.\n * `projectID` is by far the most common: it is silently ignored, so without this the message would\n * claim the option is absent while the developer stares at a line that clearly sets it.\n */\nconst confusableKey = (option: RequiredOption, config: unknown): string | undefined => {\n if (typeof config !== \"object\" || config === null) {\n return undefined\n }\n const candidates = ALIASES[option]\n return Object.keys(config).find(key => key !== option && candidates.includes(normalized(key)))\n}\n\n/** One thing that is wrong with one option, already spelled out. */\nexport interface ConfigProblem {\n option: RequiredOption\n /** Predicate completing \"<option> …\", ex. `is missing`. */\n what: string\n /** Extra lines, printed under the option, that say how to fix this particular case. */\n hints: string[]\n}\n\nconst problem = (option: RequiredOption, what: string, ...hints: (string | undefined)[]): ConfigProblem => ({\n option,\n what,\n hints: [WHAT_IT_IS[option], ...hints].filter((hint): hint is string => Boolean(hint))\n})\n\n/**\n * A backendUrl the client can actually build a request on: an absolute http(s) URL, or a path on the\n * host's own origin, which `fetch` resolves against the page.\n */\nconst diagnoseBackendUrl = (value: string): ConfigProblem | null => {\n const trimmed = value.trim()\n if (trimmed.startsWith(\"/\")) {\n return null\n }\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, which is not a URL`,\n trimmed.includes(\".\") || trimmed.includes(\":\")\n ? `It looks like a host without a protocol: write \"https://${trimmed}\" instead, or \"/${trimmed.replace(/^\\/+/, \"\")}\" if the console API answers on the same origin as this page.`\n : undefined\n )\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, whose \"${parsed.protocol.replace(\":\", \"\")}\" scheme is neither http nor https`,\n 'A bare \"host:port\" is read as a scheme: write \"http://localhost:3000/api\", not \"localhost:3000/api\".'\n )\n }\n return null\n}\n\n/** Everything wrong with one required option, or null when it is usable. */\nconst diagnose = (option: RequiredOption, config: unknown): ConfigProblem | null => {\n const value = (config as Record<string, unknown> | null | undefined)?.[option]\n const typo = confusableKey(option, config)\n const typoHint = typo ? `The configuration carries \"${typo}\", which the client ignores. The option is spelled \"${option}\".` : undefined\n\n if (value === undefined || value === null) {\n return problem(option, value === null ? \"is null\" : \"is missing\", typoHint, typo ? undefined : missingEnvHint(option))\n }\n if (typeof value !== \"string\") {\n return problem(option, `is ${described(value)}, not a string`, typoHint)\n }\n if (value.trim() === \"\") {\n return problem(option, value === \"\" ? \"is an empty string\" : \"holds nothing but whitespace\", typoHint, missingEnvHint(option))\n }\n if (PLACEHOLDER.test(value.trim())) {\n const looksLikeAnUnsetVariable = /^(undefined|null|nan)$/i.test(value.trim())\n return problem(option, `is still the placeholder ${quoted(value)}`, typoHint, looksLikeAnUnsetVariable ? missingEnvHint(option) : undefined)\n }\n if (option === \"projectId\" && value.trim() !== value) {\n // Percent encoded into the path, so the padding would travel to the backend as %20.\n return problem(\n \"projectId\",\n `is ${quoted(value)}, padded with whitespace`,\n \"Trim the value: it is percent encoded into the manifest URL, so the spaces would reach the backend as part of the id.\"\n )\n }\n return option === \"backendUrl\" ? diagnoseBackendUrl(value) : null\n}\n\n/** Every problem of a configuration, in the order the options are declared. Empty means usable. */\nexport const diagnoseConfig = (config: unknown): ConfigProblem[] =>\n ([\"backendUrl\", \"projectId\"] as const).map(option => diagnose(option, config)).filter((found): found is ConfigProblem => found !== null)\n\nconst bulleted = (problems: ConfigProblem[]): string => problems.map(({ option, what, hints }) => [` • ${option} ${what}.`, ...hints.map(hint => ` → ${hint}`)].join(\"\\n\")).join(\"\\n\")\n\nconst indented = (block: string): string =>\n block\n .split(\"\\n\")\n .map(line => (line ? ` ${line}` : line))\n .join(\"\\n\")\n\nconst howToConfigure = (integration: Integration): string => `Configure the client like this:\\n\\n${indented(SNIPPETS[integration])}\\n\\n${WHERE[integration]}`\n\nconst listed = (options: RequiredOption[]): string => (options.length > 1 ? `${options.slice(0, -1).join(\", \")} and ${options.at(-1)}` : String(options[0]))\n\n/** The message thrown by `configure()` when what it received cannot be used. */\nexport const invalidConfigMessage = (problems: ConfigProblem[], integration: Integration): string => {\n const options = problems.map(({ option }) => option)\n const headline = `${PREFIX} configure() cannot start the client: ${listed(options)} ${options.length > 1 ? \"are\" : \"is\"} not usable.`\n return `${headline}\\n\\n${bulleted(problems)}\\n\\n${howToConfigure(integration)}`\n}\n\n/** The message thrown by `configure()` when it did not even receive an object. */\nexport const noConfigMessage = (config: unknown, integration: Integration): string =>\n `${PREFIX} configure() was called with ${config === undefined ? \"no argument\" : described(config)} instead of a configuration object. It needs at least backendUrl and projectId.\\n\\n${howToConfigure(integration)}`\n\n/** The message every read rejects with while the client has no configuration at all. */\nexport const notConfiguredMessage = (caller: string, integration: Integration): string =>\n `${PREFIX} the client is not configured: ${caller} was called before configure() ever ran, so neither backendUrl nor projectId is known and no manifest can be requested.\\n\\n${howToConfigure(integration)}`\n","import type { Integration } from \"./errors\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\n\nexport interface OrchestratorState {\n config: OrchestratorConfig | null\n manifestPromise: Promise<Manifest> | null\n identities: Identities | null\n /** Set by the framework adapters as they load, so an error prints the snippet of their own API. */\n integration: Integration\n}\n\n/**\n * The state lives on `globalThis` under this key, not in a module scope variable.\n *\n * A host can end up with two copies of this package loaded at once: the app imports the ESM build\n * while something else pulls the CJS one, or the bundler config and the app resolve to different\n * chunks. Two module scopes would mean two configurations and two manifest requests, which is\n * exactly what the contract forbids. One well known global slot makes the singleton real.\n */\nexport const STATE_KEY = \"__mfe_orchestrator_client__\"\n\nconst globalSlot = globalThis as typeof globalThis & Record<typeof STATE_KEY, OrchestratorState | undefined>\n\nexport const getState = (): OrchestratorState => {\n let state = globalSlot[STATE_KEY]\n if (!state) {\n state = { config: null, manifestPromise: null, identities: null, integration: \"core\" }\n globalSlot[STATE_KEY] = state\n }\n return state\n}\n","import type { Identities } from \"./types\"\n\nexport const SESSION_ID_KEY = \"mfe-orchestrator.sessionId\"\nexport const DEVICE_ID_KEY = \"mfe-orchestrator.deviceId\"\n\nconst PROBE_KEY = \"mfe-orchestrator.probe\"\n\ntype StorageKind = \"local\" | \"session\"\n\n/**\n * Ids minted while storage was unusable. They live for the lifetime of the page so that, even\n * without storage, every request of this page load carries one stable pair of ids.\n */\nconst inMemoryIds = new Map<string, string>()\n\nconst uuidFromRandomBytes = (bytes: Uint8Array): string => {\n bytes[6] = (bytes[6] & 0x0f) | 0x40\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n const hex: string[] = []\n for (const byte of bytes) {\n hex.push(byte.toString(16).padStart(2, \"0\"))\n }\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`\n}\n\n/**\n * A v4 UUID. `crypto.randomUUID` is the intended path; the two fallbacks only exist so that a page\n * served over plain http, or an exotic runtime, still gets an id instead of an exception.\n */\nexport const newId = (): string => {\n const cryptoApi = globalThis.crypto\n try {\n if (typeof cryptoApi?.randomUUID === \"function\") {\n return cryptoApi.randomUUID()\n }\n if (typeof cryptoApi?.getRandomValues === \"function\") {\n return uuidFromRandomBytes(cryptoApi.getRandomValues(new Uint8Array(16)))\n }\n } catch {\n // fall through to the non cryptographic fallback\n }\n const bytes = new Uint8Array(16)\n for (let index = 0; index < bytes.length; index++) {\n bytes[index] = Math.floor(Math.random() * 256)\n }\n return uuidFromRandomBytes(bytes)\n}\n\n/**\n * The requested storage, or `null` when it is missing or unusable.\n *\n * Both the property access and the write can throw: Safari in private mode exposes the object and\n * then refuses `setItem`, some hardened browsers throw a SecurityError on the access itself. The\n * write probe is the only reliable way to tell a usable storage from a decorative one.\n */\nconst openStorage = (kind: StorageKind): Storage | null => {\n try {\n const storage = kind === \"local\" ? globalThis.localStorage : globalThis.sessionStorage\n if (!storage) {\n return null\n }\n storage.setItem(PROBE_KEY, \"1\")\n storage.removeItem(PROBE_KEY)\n return storage\n } catch {\n return null\n }\n}\n\n/**\n * The id under `key`, read from storage and created on first use. Falls back to an id kept in\n * memory when storage cannot be used, so this never throws out of the SDK.\n */\nconst persistentId = (kind: StorageKind, key: string): string => {\n const storage = openStorage(kind)\n if (storage) {\n try {\n const stored = storage.getItem(key)\n if (stored) {\n return stored\n }\n const created = newId()\n storage.setItem(key, created)\n return created\n } catch {\n // storage passed the probe and failed anyway: keep going with an in memory id\n }\n }\n const remembered = inMemoryIds.get(key)\n if (remembered) {\n return remembered\n }\n const created = newId()\n inMemoryIds.set(key, created)\n return created\n}\n\n/** Reads, and creates when needed, the session and device ids. */\nexport const readIdentities = (): Identities => ({\n sessionId: persistentId(\"session\", SESSION_ID_KEY),\n deviceId: persistentId(\"local\", DEVICE_ID_KEY)\n})\n","import { diagnoseConfig, type Integration, invalidConfigMessage, noConfigMessage, notConfiguredMessage, PREFIX } from \"./errors\"\nimport { getState } from \"./state\"\nimport { readIdentities } from \"./storage\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\n\nexport type { ConfigProblem, Integration } from \"./errors\"\nexport type { GlobalVariable, Identities, Manifest, Microfrontend, OrchestratorConfig } from \"./types\"\n\nconst withoutTrailingSlash = (value: string): string => value.replace(/\\/+$/, \"\")\n\nconst resolveUserId = async (userId: OrchestratorConfig[\"userId\"]): Promise<string | undefined> => {\n const value = typeof userId === \"function\" ? await userId() : userId\n return value === undefined || value === null || value === \"\" ? undefined : String(value)\n}\n\n/** Everything but the identity: the part of the configuration that is fixed for a page load. */\nconst sameTarget = (left: OrchestratorConfig, right: OrchestratorConfig): boolean =>\n left.backendUrl === right.backendUrl && left.projectId === right.projectId && left.environment === right.environment\n\nconst sameConfig = (left: OrchestratorConfig, right: OrchestratorConfig): boolean => sameTarget(left, right) && left.userId === right.userId\n\n/**\n * Whether replacing the identity would change nothing. Two getters are never considered equal, even the\n * same one twice: what a function returns is exactly what this side cannot know, so a host handing one\n * over is taken at its word and the manifest is re-fetched.\n */\nconst sameUserId = (left: OrchestratorConfig[\"userId\"], right: OrchestratorConfig[\"userId\"]): boolean => typeof left !== \"function\" && typeof right !== \"function\" && left === right\n\n/**\n * Rejects a configuration the client could not use, with a message that names the option, shows what\n * actually arrived and prints the call to write. environment is deliberately not required: without\n * it the backend resolves it from the domain. It is still checked for type, because a non string\n * there would silently end up percent encoded into the path.\n */\nconst requireConfig = (config: OrchestratorConfig, integration: Integration): void => {\n if (typeof config !== \"object\" || config === null) {\n throw new Error(noConfigMessage(config, integration))\n }\n const problems = diagnoseConfig(config)\n if (problems.length > 0) {\n throw new Error(invalidConfigMessage(problems, integration))\n }\n if (config.environment !== undefined && config.environment !== null && typeof config.environment !== \"string\") {\n throw new Error(\n `${PREFIX} configure() received environment as a ${typeof config.environment}, not a string. Pass the environment slug as it appears in the console, ex. \"DEV\", or leave it out to let the backend resolve it from the domain of this page.`\n )\n }\n}\n\n/** Notices about a stored configuration that works but probably does not do what the host meant. */\nconst warnAboutConfig = (config: OrchestratorConfig): void => {\n if (typeof config.environment === \"string\" && config.environment.trim() === \"\") {\n console.warn(\n `${PREFIX} configure() received an empty environment, so the client falls back to the auto routes and the backend resolves the environment from the domain of this page. Remove the option if that is what you want, or check the variable that feeds it.`\n )\n }\n}\n\n/**\n * Two shapes, one per route family. With an explicit environment the slug is the last segment; with\n * no environment the \"auto\" segment takes its place before the project id and the backend resolves\n * the environment from the domain the request comes from.\n */\nconst manifestPath = (config: OrchestratorConfig): string => {\n const projectId = encodeURIComponent(config.projectId)\n return config.environment ? `/serve/all/${projectId}/${encodeURIComponent(config.environment)}` : `/serve/all/auto/${projectId}`\n}\n\nconst manifestUrl = async (config: OrchestratorConfig): Promise<string> => {\n const { sessionId, deviceId } = identities()\n const query = new URLSearchParams({ mfeSessionId: sessionId, mfeDeviceId: deviceId })\n // Resolved as late as possible: the host may only know the user after its own auth round trip.\n const userId = await resolveUserId(config.userId)\n if (userId) {\n query.set(\"mfeUserId\", userId)\n }\n return `${withoutTrailingSlash(config.backendUrl)}${manifestPath(config)}?${query.toString()}`\n}\n\n/**\n * What a status usually means on this route. The backend answers the same 404 for an unknown project\n * and for an unknown environment, and the two are indistinguishable from here, so both are named.\n */\nconst statusHint = (status: number, config: OrchestratorConfig): string => {\n if (status === 404) {\n const environment = config.environment\n ? `the environment \"${config.environment}\" does not exist in it`\n : \"no environment of that project declares the domain this page is served on, which is what the auto route resolves on\"\n return `\\n\\nA 404 on this route means the backend did not find what the URL names: either the project id \"${config.projectId}\" is not a project of this console, or ${environment}. Check both in the console, and check that backendUrl points at the console API of the same instance.`\n }\n if (status === 401 || status === 403) {\n return `\\n\\nThe console refused the request. Check that the project id \"${config.projectId}\" belongs to the instance backendUrl points at, and that this domain is allowed to read its manifest.`\n }\n return \"\"\n}\n\nconst fetchManifest = async (config: OrchestratorConfig): Promise<Manifest> => {\n const url = await manifestUrl(config)\n // No retry in v1: whatever fetch throws travels straight to the caller.\n const response = await fetch(url, { headers: { accept: \"application/json\" } })\n if (!response.ok) {\n throw new Error(`${PREFIX} the manifest request failed with ${response.status} ${response.statusText}. GET ${url}${statusHint(response.status, config)}`)\n }\n const payload = (await response.json()) as Partial<Manifest> | null\n return {\n globalVariables: payload?.globalVariables ?? [],\n microfrontends: payload?.microfrontends ?? []\n }\n}\n\n/**\n * Hands the client its configuration. Call it once, synchronously, before any remote is imported.\n *\n * `backendUrl` and `projectId` are required. `environment` is not: omitting it makes the client use\n * the \"auto\" routes, where the backend resolves the environment from the domain of the host page.\n *\n * Idempotent: calling it again with the same options is a no op, so a framework provider may safely\n * call it on every render. A second call with different options is ignored, with a warning, because\n * the manifest of this page load may already be in flight or resolved. The user is the exception, and\n * it changes through `setUserId()`, not through a second call here.\n */\nexport const configure = (config: OrchestratorConfig): void => {\n const state = getState()\n requireConfig(config, state.integration)\n const current = state.config\n if (current) {\n if (!sameConfig(current, config)) {\n console.warn(\n sameTarget(current, config)\n ? `${PREFIX} configure() was called again with a different userId. The configuration is fixed for this page load, so this one is ignored: call setUserId() instead, which is the supported way to change the user mid session and also drops the memoized manifest, so the next read is decided on the new identity.`\n : `${PREFIX} configure() was called again with a different configuration. The first one is kept: ${JSON.stringify({ backendUrl: current.backendUrl, projectId: current.projectId, environment: current.environment })}.`\n )\n }\n return\n }\n state.config = { ...config }\n warnAboutConfig(config)\n}\n\n/**\n * Replaces the identity the backend decides a user based canary on, after the client was configured.\n *\n * `configure()` is deliberately once only, and this is the one option that legitimately changes while\n * the page is alive: a login, a logout, an account switch. So it gets its own setter, and that setter\n * does what `configure()` must not — it drops the memoized manifest, so the next `manifest()`,\n * `remoteUrl()` or `globalVariables()` asks the backend again and is answered for the new user.\n *\n * Pass `undefined` on logout: the next request then carries no `mfeUserId` at all, which is what makes\n * the backend hand out the stable version again.\n *\n * What this does NOT do is reload the remotes already imported. The federation runtime keeps the\n * container it has, so a microfrontend already on the page stays on the version drawn for the previous\n * user, and only remotes resolved after this call see the new one. When the whole page must be\n * consistent, follow the identity change with a reload; when the host mounts its remotes behind its own\n * auth guard, calling this before the guard opens is enough.\n *\n * Setting the same plain value again is a no op, so an auth store may call it on every emission without\n * costing a request. A getter is always taken as a change, since what it returns is precisely what this\n * side cannot know.\n *\n * A request already in flight is not cancelled: whoever is awaiting it still receives the manifest of\n * the previous identity. Only the memo is dropped.\n */\nexport const setUserId = (userId: OrchestratorConfig[\"userId\"]): void => {\n const state = getState()\n const current = state.config\n if (!current) {\n throw new Error(notConfiguredMessage(\"setUserId()\", state.integration))\n }\n if (sameUserId(current.userId, userId)) {\n return\n }\n state.config = { ...current, userId }\n state.manifestPromise = null\n}\n\n/**\n * @internal Lets a framework adapter say which package the host is really using, so a configuration\n * error prints the snippet of that API instead of the bare `configure()` one. Idempotent, and never\n * needed by an application: the adapters call it as they load.\n */\nexport const registerIntegration = (integration: Integration): void => {\n getState().integration = integration\n}\n\n/**\n * The whole manifest of the environment, fetched once per page load and memoized as a promise, so\n * that concurrent callers share the single request in flight.\n *\n * A successful result is memoized for good. A failed attempt is not: the memo is dropped when the\n * shared attempt settles as rejected, so the next caller starts a fresh request. That is not a retry\n * — nothing here loops or backs off — it only means one flaky lookup at boot does not condemn the\n * page to reject every `remoteUrl()` until a full reload.\n */\nconst loadManifest = (caller: string): Promise<Manifest> => {\n const state = getState()\n const config = state.config\n if (!config) {\n // Not memoized: the host may still configure the client and try again.\n return Promise.reject(new Error(notConfiguredMessage(caller, state.integration)))\n }\n if (!state.manifestPromise) {\n // Assigned before the first await inside fetchManifest, which is what makes N concurrent\n // callers collapse onto one request.\n const attempt = fetchManifest(config)\n state.manifestPromise = attempt\n // Cleared once, when the shared attempt settles, not in each caller's own catch: every\n // caller already waiting on this attempt still gets its rejection. The identity check keeps\n // a late failure from evicting a newer attempt.\n attempt.catch(() => {\n if (state.manifestPromise === attempt) {\n state.manifestPromise = null\n }\n })\n }\n return state.manifestPromise\n}\n\n/** The whole manifest of the environment. See `loadManifest` for the memoization contract. */\nexport const manifest = (): Promise<Manifest> => loadManifest(\"manifest()\")\n\n/**\n * The ready to use, version pinned URL of a remote. Awaits the manifest internally.\n *\n * The returned URL is used verbatim: the host never parses the version out of it and never strips\n * the `_v/<version>/` segment, or a classic script would load its chunks off another version.\n */\nexport const remoteUrl = async (slug: string): Promise<string> => {\n const { microfrontends } = await loadManifest(`remoteUrl(\"${slug}\")`)\n const found = microfrontends.find(microfrontend => microfrontend.slug === slug)\n if (!found) {\n const available = microfrontends.map(microfrontend => `\"${microfrontend.slug}\"`).join(\", \")\n const environment = getState().config?.environment\n // With no configured environment the host cannot name the one it was served: only the backend knows.\n const where = environment ? `environment \"${environment}\"` : \"the environment resolved from this domain\"\n throw new Error(`${PREFIX} unknown microfrontend slug \"${slug}\". Available in ${where}: ${available || \"none, this environment serves no microfrontend\"}.`)\n }\n if (!found.url) {\n throw new Error(`${PREFIX} the microfrontend \"${slug}\" is in the manifest but carries no url. Check its deployment in the console.`)\n }\n return found.url\n}\n\n/** The global variables of the environment, as a plain object. */\nexport const globalVariables = async (): Promise<Record<string, string>> => {\n const { globalVariables: variables } = await loadManifest(\"globalVariables()\")\n const result: Record<string, string> = {}\n for (const variable of variables) {\n if (variable && typeof variable.key === \"string\") {\n result[variable.key] = variable.value\n }\n }\n return result\n}\n\n/**\n * The session and device ids of this page, exposed for telemetry and debugging. Created on first\n * use and stable for the lifetime of the page, whether or not storage is available.\n */\nexport const identities = (): Identities => {\n const state = getState()\n if (!state.identities) {\n state.identities = readIdentities()\n }\n return state.identities\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/state.ts","../src/storage.ts","../src/webpack.ts","../src/index.ts"],"names":["created"],"mappings":";AASO,IAAM,MAAA,GAAS,gCAAA;AAQtB,IAAM,mBAAA,GAAsB,0CAAA;AAC5B,IAAM,kBAAA,GAAqB,0BAAA;AAE3B,IAAM,QAAA,GAAwC;AAAA,EAC1C,IAAA,EAAM,CAAA;;AAAA;AAAA,iBAAA,EAGS,mBAAmB,CAAA;AAAA,gBAAA,EACpB,kBAAkB,CAAA;AAAA,EAAA,CAAA;AAAA,EAEhC,KAAA,EAAO,CAAA;;AAAA,6CAAA,EAEoC,mBAAmB,kBAAkB,kBAAkB,CAAA;AAAA;AAAA,uBAAA,CAAA;AAAA,EAGlG,GAAA,EAAK,CAAA;;AAAA,0CAAA,EAEmC,mBAAmB,kBAAkB,kBAAkB,CAAA,KAAA,CAAA;AAAA,EAC/F,OAAA,EAAS,CAAA;;AAAA;AAAA,mDAAA,EAGwC,mBAAmB,kBAAkB,kBAAkB,CAAA;AAAA,EAAA;AAE5G,CAAA;AAEA,IAAM,KAAA,GAAqC;AAAA,EACvC,IAAA,EAAM,0FAAA;AAAA,EACN,KAAA,EAAO,+KAAA;AAAA,EACP,GAAA,EAAK,yKAAA;AAAA,EACL,OAAA,EAAS;AACb,CAAA;AAEA,IAAM,UAAA,GAA6C;AAAA,EAC/C,UAAA,EAAY,kEAAkE,mBAAmB,CAAA,gEAAA,CAAA;AAAA,EACjG,SAAA,EAAW,gGAAgG,kBAAkB,CAAA,EAAA;AACjI,CAAA;AAGA,IAAM,cAAA,GAA4E;AAAA,EAC9E,UAAA,EAAY,EAAE,IAAA,EAAM,sBAAA,EAAwB,SAAS,iBAAA,EAAkB;AAAA,EACvE,SAAA,EAAW,EAAE,IAAA,EAAM,qBAAA,EAAuB,SAAS,gBAAA;AACvD,CAAA;AAQA,IAAM,cAAA,GAAiB,CAAC,MAAA,KACpB,CAAA,mGAAA,EAAsG,cAAA,CAAe,MAAM,CAAA,CAAE,IAAI,CAAA,WAAA,EAAc,cAAA,CAAe,MAAM,CAAA,CAAE,OAAO,CAAA,sQAAA,CAAA;AAGjL,IAAM,WAAA,GAAc,kHAAA;AAGpB,IAAM,MAAA,GAAS,CAAC,KAAA,KAA0B,IAAA,CAAK,UAAU,KAAA,CAAM,MAAA,GAAS,GAAA,GAAM,CAAA,EAAG,MAAM,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC,WAAM,KAAK,CAAA;AAE/G,IAAM,SAAA,GAAY,CAAC,KAAA,KAA2B;AAC1C,EAAA,IAAI,UAAU,IAAA,EAAM;AAChB,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,IAAA,OAAO,UAAA;AAAA,EACX;AACA,EAAA,MAAM,OAAO,OAAO,KAAA;AACpB,EAAA,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,UAAA,GAAa,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,GAAK,CAAA,EAAA,EAAK,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA,CAAA;AAC/F,CAAA;AAGA,IAAM,UAAA,GAAa,CAAC,GAAA,KAAwB,GAAA,CAAI,aAAY,CAAE,OAAA,CAAQ,cAAc,EAAE,CAAA;AAEtF,IAAM,OAAA,GAA4C;AAAA,EAC9C,UAAA,EAAY,CAAC,YAAA,EAAc,gBAAA,EAAkB,UAAU,SAAA,EAAW,YAAA,EAAc,OAAO,SAAS,CAAA;AAAA,EAChG,WAAW,CAAC,WAAA,EAAa,SAAA,EAAW,WAAA,EAAa,eAAe,YAAY;AAChF,CAAA;AAOA,IAAM,aAAA,GAAgB,CAAC,MAAA,EAAwB,MAAA,KAAwC;AACnF,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,IAAA,EAAM;AAC/C,IAAA,OAAO,MAAA;AAAA,EACX;AACA,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,IAAA,CAAK,CAAA,GAAA,KAAO,GAAA,KAAQ,MAAA,IAAU,UAAA,CAAW,QAAA,CAAS,UAAA,CAAW,GAAG,CAAC,CAAC,CAAA;AACjG,CAAA;AAWA,IAAM,OAAA,GAAU,CAAC,MAAA,EAAwB,IAAA,EAAA,GAAiB,KAAA,MAAkD;AAAA,EACxG,MAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA,EAAO,CAAC,UAAA,CAAW,MAAM,CAAA,EAAG,GAAG,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAyB,OAAA,CAAQ,IAAI,CAAC;AACxF,CAAA,CAAA;AAMA,IAAM,kBAAA,GAAqB,CAAC,KAAA,KAAwC;AAChE,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,EAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA;AAAA,EACX;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACA,IAAA,MAAA,GAAS,IAAI,IAAI,OAAO,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACJ,IAAA,OAAO,OAAA;AAAA,MACH,YAAA;AAAA,MACA,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK,CAAC,CAAA,oBAAA,CAAA;AAAA,MACnB,QAAQ,QAAA,CAAS,GAAG,CAAA,IAAK,OAAA,CAAQ,SAAS,GAAG,CAAA,GACvC,CAAA,wDAAA,EAA2D,OAAO,mBAAmB,OAAA,CAAQ,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA,6DAAA,CAAA,GAChH;AAAA,KACV;AAAA,EACJ;AACA,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,OAAA,IAAW,MAAA,CAAO,aAAa,QAAA,EAAU;AAC7D,IAAA,OAAO,OAAA;AAAA,MACH,YAAA;AAAA,MACA,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK,CAAC,CAAA,SAAA,EAAY,OAAO,QAAA,CAAS,OAAA,CAAQ,GAAA,EAAK,EAAE,CAAC,CAAA,kCAAA,CAAA;AAAA,MAC/D;AAAA,KACJ;AAAA,EACJ;AACA,EAAA,OAAO,IAAA;AACX,CAAA;AAGA,IAAM,QAAA,GAAW,CAAC,MAAA,EAAwB,MAAA,KAA0C;AAChF,EAAA,MAAM,KAAA,GAAS,SAAwD,MAAM,CAAA;AAC7E,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,EAAQ,MAAM,CAAA;AACzC,EAAA,MAAM,WAAW,IAAA,GAAO,CAAA,2BAAA,EAA8B,IAAI,CAAA,oDAAA,EAAuD,MAAM,CAAA,EAAA,CAAA,GAAO,MAAA;AAE9H,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACvC,IAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,KAAA,KAAU,IAAA,GAAO,SAAA,GAAY,YAAA,EAAc,QAAA,EAAU,IAAA,GAAO,MAAA,GAAY,cAAA,CAAe,MAAM,CAAC,CAAA;AAAA,EACzH;AACA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,IAAA,OAAO,QAAQ,MAAA,EAAQ,CAAA,GAAA,EAAM,UAAU,KAAK,CAAC,kBAAkB,QAAQ,CAAA;AAAA,EAC3E;AACA,EAAA,IAAI,KAAA,CAAM,IAAA,EAAK,KAAM,EAAA,EAAI;AACrB,IAAA,OAAO,OAAA,CAAQ,QAAQ,KAAA,KAAU,EAAA,GAAK,uBAAuB,8BAAA,EAAgC,QAAA,EAAU,cAAA,CAAe,MAAM,CAAC,CAAA;AAAA,EACjI;AACA,EAAA,IAAI,WAAA,CAAY,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA,EAAG;AAChC,IAAA,MAAM,wBAAA,GAA2B,yBAAA,CAA0B,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC5E,IAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,yBAAA,EAA4B,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA,EAAI,QAAA,EAAU,wBAAA,GAA2B,cAAA,CAAe,MAAM,CAAA,GAAI,MAAS,CAAA;AAAA,EAC/I;AACA,EAAA,IAAI,MAAA,KAAW,WAAA,IAAe,KAAA,CAAM,IAAA,OAAW,KAAA,EAAO;AAElD,IAAA,OAAO,OAAA;AAAA,MACH,WAAA;AAAA,MACA,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK,CAAC,CAAA,wBAAA,CAAA;AAAA,MACnB;AAAA,KACJ;AAAA,EACJ;AACA,EAAA,OAAO,MAAA,KAAW,YAAA,GAAe,kBAAA,CAAmB,KAAK,CAAA,GAAI,IAAA;AACjE,CAAA;AAGO,IAAM,iBAAiB,CAAC,MAAA,KAC1B,CAAC,YAAA,EAAc,WAAW,EAAY,GAAA,CAAI,CAAA,MAAA,KAAU,QAAA,CAAS,MAAA,EAAQ,MAAM,CAAC,CAAA,CAAE,OAAO,CAAC,KAAA,KAAkC,UAAU,IAAI,CAAA;AAE3I,IAAM,QAAA,GAAW,CAAC,QAAA,KAAsC,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAM,KAAM,CAAC,YAAO,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,CAAA,EAAK,GAAG,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,KAAQ,gBAAW,IAAI,CAAA,CAAE,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,KAAK,IAAI,CAAA;AAE3L,IAAM,WAAW,CAAC,KAAA,KACd,KAAA,CACK,KAAA,CAAM,IAAI,CAAA,CACV,GAAA,CAAI,CAAA,IAAA,KAAS,IAAA,GAAO,OAAO,IAAI,CAAA,CAAA,GAAK,IAAK,CAAA,CACzC,KAAK,IAAI,CAAA;AAElB,IAAM,cAAA,GAAiB,CAAC,WAAA,KAAqC,CAAA;;AAAA,EAAsC,QAAA,CAAS,QAAA,CAAS,WAAW,CAAC,CAAC;;AAAA,EAAO,KAAA,CAAM,WAAW,CAAC,CAAA,CAAA;AAE3J,IAAM,MAAA,GAAS,CAAC,OAAA,KAAuC,OAAA,CAAQ,MAAA,GAAS,IAAI,CAAA,EAAG,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,KAAK,IAAI,CAAC,CAAA,KAAA,EAAQ,OAAA,CAAQ,EAAA,CAAG,EAAE,CAAC,CAAA,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAC,CAAA;AAGnJ,IAAM,oBAAA,GAAuB,CAAC,QAAA,EAA2B,WAAA,KAAqC;AACjG,EAAA,MAAM,UAAU,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,MAAA,OAAa,MAAM,CAAA;AACnD,EAAA,MAAM,QAAA,GAAW,CAAA,EAAG,MAAM,CAAA,sCAAA,EAAyC,MAAA,CAAO,OAAO,CAAC,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,KAAA,GAAQ,IAAI,CAAA,YAAA,CAAA;AACvH,EAAA,OAAO,GAAG,QAAQ;;AAAA,EAAO,QAAA,CAAS,QAAQ,CAAC;;AAAA,EAAO,cAAA,CAAe,WAAW,CAAC,CAAA,CAAA;AACjF,CAAA;AAGO,IAAM,eAAA,GAAkB,CAAC,MAAA,EAAiB,WAAA,KAC7C,CAAA,EAAG,MAAM,CAAA,6BAAA,EAAgC,MAAA,KAAW,MAAA,GAAY,aAAA,GAAgB,SAAA,CAAU,MAAM,CAAC,CAAA;;AAAA,EAAsF,cAAA,CAAe,WAAW,CAAC,CAAA,CAAA;AAG/M,IAAM,uBAAuB,CAAC,MAAA,EAAgB,gBACjD,CAAA,EAAG,MAAM,kCAAkC,MAAM,CAAA;;AAAA,EAA8H,cAAA,CAAe,WAAW,CAAC,CAAA,CAAA;;;ACzLvM,IAAM,SAAA,GAAY,6BAAA;AAEzB,IAAM,UAAA,GAAa,UAAA;AAEZ,IAAM,WAAW,MAAyB;AAC7C,EAAA,IAAI,KAAA,GAAQ,WAAW,SAAS,CAAA;AAChC,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,KAAA,GAAQ,EAAE,QAAQ,IAAA,EAAM,eAAA,EAAiB,MAAM,UAAA,EAAY,IAAA,EAAM,aAAa,MAAA,EAAO;AACrF,IAAA,UAAA,CAAW,SAAS,CAAA,GAAI,KAAA;AAAA,EAC5B;AACA,EAAA,OAAO,KAAA;AACX,CAAA;;;ACpCO,IAAM,cAAA,GAAiB,4BAAA;AACvB,IAAM,aAAA,GAAgB,2BAAA;AAE7B,IAAM,SAAA,GAAY,wBAAA;AAQlB,IAAM,WAAA,uBAAkB,GAAA,EAAoB;AAE5C,IAAM,mBAAA,GAAsB,CAAC,KAAA,KAA8B;AACvD,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAI,EAAA,GAAQ,EAAA;AAC/B,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAI,EAAA,GAAQ,GAAA;AAC/B,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,IAAA,GAAA,CAAI,IAAA,CAAK,KAAK,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,CAAA,EAAG,IAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,CAAA,EAAI,IAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,CAAA,EAAI,IAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,CAAA,EAAI,IAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,CAAA,EAAI,IAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA,CAAA;AACzJ,CAAA;AAMO,IAAM,QAAQ,MAAc;AAC/B,EAAA,MAAM,YAAY,UAAA,CAAW,MAAA;AAC7B,EAAA,IAAI;AACA,IAAA,IAAI,OAAO,SAAA,EAAW,UAAA,KAAe,UAAA,EAAY;AAC7C,MAAA,OAAO,UAAU,UAAA,EAAW;AAAA,IAChC;AACA,IAAA,IAAI,OAAO,SAAA,EAAW,eAAA,KAAoB,UAAA,EAAY;AAClD,MAAA,OAAO,oBAAoB,SAAA,CAAU,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAC,CAAA;AAAA,IAC5E;AAAA,EACJ,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,KAAA,CAAM,QAAQ,KAAA,EAAA,EAAS;AAC/C,IAAA,KAAA,CAAM,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,KAAW,GAAG,CAAA;AAAA,EACjD;AACA,EAAA,OAAO,oBAAoB,KAAK,CAAA;AACpC,CAAA;AASA,IAAM,WAAA,GAAc,CAAC,IAAA,KAAsC;AACvD,EAAA,IAAI;AACA,IAAA,MAAM,OAAA,GAAU,IAAA,KAAS,OAAA,GAAU,UAAA,CAAW,eAAe,UAAA,CAAW,cAAA;AACxE,IAAA,IAAI,CAAC,OAAA,EAAS;AACV,MAAA,OAAO,IAAA;AAAA,IACX;AACA,IAAA,OAAA,CAAQ,OAAA,CAAQ,WAAW,GAAG,CAAA;AAC9B,IAAA,OAAA,CAAQ,WAAW,SAAS,CAAA;AAC5B,IAAA,OAAO,OAAA;AAAA,EACX,CAAA,CAAA,MAAQ;AACJ,IAAA,OAAO,IAAA;AAAA,EACX;AACJ,CAAA;AAMA,IAAM,YAAA,GAAe,CAAC,IAAA,EAAmB,GAAA,KAAwB;AAC7D,EAAA,MAAM,OAAA,GAAU,YAAY,IAAI,CAAA;AAChC,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,IAAI;AACA,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AAClC,MAAA,IAAI,MAAA,EAAQ;AACR,QAAA,OAAO,MAAA;AAAA,MACX;AACA,MAAA,MAAMA,WAAU,KAAA,EAAM;AACtB,MAAA,OAAA,CAAQ,OAAA,CAAQ,KAAKA,QAAO,CAAA;AAC5B,MAAA,OAAOA,QAAAA;AAAA,IACX,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACJ;AACA,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA;AACtC,EAAA,IAAI,UAAA,EAAY;AACZ,IAAA,OAAO,UAAA;AAAA,EACX;AACA,EAAA,MAAM,UAAU,KAAA,EAAM;AACtB,EAAA,WAAA,CAAY,GAAA,CAAI,KAAK,OAAO,CAAA;AAC5B,EAAA,OAAO,OAAA;AACX,CAAA;AAGO,IAAM,iBAAiB,OAAmB;AAAA,EAC7C,SAAA,EAAW,YAAA,CAAa,SAAA,EAAW,cAAc,CAAA;AAAA,EACjD,QAAA,EAAU,YAAA,CAAa,OAAA,EAAS,aAAa;AACjD,CAAA,CAAA;;;ACxFO,IAAM,gBAAA,GAAmB;AAYzB,IAAM,oBAAA,GAAuB;AAEpC,IAAM,WAAA,GAAc,UAAA;AAQb,IAAM,gBAAgB,MAAY;AACrC,EAAA,MAAM,QAAA,GAAW,YAAY,gBAAgB,CAAA;AAC7C,EAAA,MAAM,SAAA,GAAyC,YAAY,EAAC;AAC5D,EAAA,IAAI,OAAO,SAAA,CAAU,iBAAA,KAAsB,UAAA,EAAY;AACnD,IAAA,SAAA,CAAU,iBAAA,GAAoB,iBAAA;AAAA,EAClC;AACA,EAAA,WAAA,CAAY,gBAAgB,CAAA,GAAI,SAAA;AACpC,CAAA;AAEA,IAAM,gBAAA,GAAmB,CAAC,KAAA,KAA2E;AACjG,EAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AACnB,IAAA,IAAI,UAAU,MAAY;AAAA,IAAC,CAAA;AAC3B,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAc,CAAA,MAAA,KAAU;AACxC,MAAA,OAAA,GAAU,MAAA;AAAA,IACd,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,UAAA,GAAa,EAAE,OAAA,EAAS,OAAA,EAAQ;AAAA,EAC1C;AACA,EAAA,OAAO,KAAA,CAAM,UAAA;AACjB,CAAA;AAGO,IAAM,iBAAiB,MAAY;AACtC,EAAA,gBAAA,CAAiB,QAAA,EAAU,CAAA,CAAE,OAAA,EAAQ;AACzC,CAAA;AAQA,IAAM,cAAA,GAAiB,CAAC,MAAA,KAAkC;AACtD,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,IAAI,MAAM,MAAA,EAAQ;AACd,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EAC3B;AACA,EAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC1C,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC3B,MAAA,MAAA;AAAA,QACI,IAAI,KAAA;AAAA,UACA,CAAA,EAAG,oBAAA,CAAqB,MAAA,EAAQ,KAAA,CAAM,WAAW,CAAC;;AAAA,kBAAA,EAAyB,uBAAuB,GAAI,CAAA,kQAAA;AAAA;AAC1G,OACJ;AAAA,IACJ,GAAG,oBAAoB,CAAA;AACvB,IAAA,gBAAA,CAAiB,KAAK,CAAA,CAAE,OAAA,CAAQ,IAAA,CAAK,MAAM;AACvC,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,OAAA,EAAQ;AAAA,IACZ,CAAC,CAAA;AAAA,EACL,CAAC,CAAA;AACL,CAAA;AAOA,IAAM,eAAA,GAAkB,CAAC,GAAA,EAAa,IAAA,KAAgC;AAClE,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,KAAA,CAAM,aAAA,yBAAsB,GAAA,EAAI;AAChC,EAAA,MAAM,UAAU,KAAA,CAAM,aAAA;AACtB,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC7B,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,MAAM,IAAA,GAAO,IAAI,OAAA,CAAc,CAAC,SAAS,MAAA,KAAW;AAChD,IAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,IAAI,MAAM,CAAA,EAAG,MAAM,uBAAuB,IAAI,CAAA,oCAAA,EAAuC,GAAG,CAAA,8BAAA,CAAgC,CAAC,CAAA;AAChI,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAA,CAAO,GAAA,GAAM,GAAA;AACb,IAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,IAAA,MAAA,CAAO,MAAA,GAAS,MAAM,OAAA,EAAQ;AAC9B,IAAA,MAAA,CAAO,UAAU,MAAM;AACnB,MAAA,MAAA,CAAO,MAAA,EAAO;AACd,MAAA,MAAA;AAAA,QACI,IAAI,KAAA;AAAA,UACA,CAAA,EAAG,MAAM,CAAA,sBAAA,EAAyB,IAAI,yBAAyB,GAAG,CAAA,kQAAA;AAAA;AACtE,OACJ;AAAA,IACJ,CAAA;AACA,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,MAAM,CAAA;AAAA,EACpC,CAAC,CAAA;AACD,EAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,IAAI,CAAA;AACrB,EAAA,IAAA,CAAK,MAAM,MAAM;AACb,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,KAAM,IAAA,EAAM;AAC3B,MAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,IACtB;AAAA,EACJ,CAAC,CAAA;AACD,EAAA,OAAO,IAAA;AACX,CAAA;AAEA,IAAM,WAAA,GAAc,CAAC,KAAA,KACjB,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,OAAQ,KAAA,CAA2B,GAAA,KAAQ,UAAA,IAAc,OAAQ,MAA2B,IAAA,KAAS,UAAA;AAGxJ,IAAM,iBAAiB,MAAgB;AACnC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,EAAG;AACxC,IAAA,IAAI;AACA,MAAA,IAAI,WAAA,CAAY,WAAA,CAAY,GAAG,CAAC,CAAA,EAAG;AAC/B,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,CAAG,CAAA;AAAA,MACzB;AAAA,IACJ,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACJ;AACA,EAAA,OAAO,KAAA;AACX,CAAA;AAEA,IAAM,uBAAA,GAA0B,CAAC,IAAA,EAAc,KAAA,EAAe,GAAA,KAAwB;AAClF,EAAA,MAAM,QAAQ,cAAA,EAAe;AAC7B,EAAA,OAAO,GAAG,MAAM,CAAA,sBAAA,EAAyB,IAAI,CAAA,cAAA,EAAiB,GAAG,qBAAqB,KAAK,CAAA,0KAAA,EACvF,KAAA,CAAM,MAAA,GAAS,IAAI,CAAA,yBAAA,EAA4B,KAAA,CAAM,KAAK,IAAI,CAAC,MAAM,8CACzE,CAAA,kGAAA,CAAA;AACJ,CAAA;AAOA,IAAM,OAAA,GAAU,CAAC,SAAA,KAAkD;AAC/D,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,KAAA,CAAM,UAAA,yBAAmB,OAAA,EAAQ;AACjC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA;AAC5C,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,IAAI,WAAA,GAA0C,IAAA;AAC9C,EAAA,MAAM,KAAA,GAA0B;AAAA,IAC5B,GAAA,EAAK,CAAA,MAAA,KAAU,SAAA,CAAU,GAAA,CAAI,MAAM,CAAA;AAAA,IACnC,IAAA,EAAM,CAAC,UAAA,EAAY,SAAA,KAAc;AAC7B,MAAA,IAAI,CAAC,WAAA,EAAa;AACd,QAAA,WAAA,GAAc,EAAE,MAAA,EAAQ,SAAA,CAAU,IAAA,CAAK,UAAA,EAAY,SAAS,CAAA,EAAE;AAAA,MAClE;AACA,MAAA,OAAO,WAAA,CAAY,MAAA;AAAA,IACvB;AAAA,GACJ;AACA,EAAA,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,SAAA,EAAW,KAAK,CAAA;AACrC,EAAA,OAAO,KAAA;AACX,CAAA;AAmBO,IAAM,iBAAA,GAAoB,OAAO,IAAA,EAAc,KAAA,KAA8C;AAChG,EAAA,MAAM,MAAA,GAAS,sBAAsB,IAAI,CAAA,EAAA,CAAA;AACzC,EAAA,MAAM,eAAe,MAAM,CAAA;AAC3B,EAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,IAAI,CAAA;AAChC,EAAA,MAAM,IAAA,GAAO,KAAA,IAAA,CAAU,MAAM,QAAA,EAAS,EAAG,cAAA,CAAe,IAAA,CAAK,CAAA,aAAA,KAAiB,aAAA,CAAc,IAAA,KAAS,IAAI,CAAA,EAAG,eAAA;AAC5G,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,MAAM,iFAAiF,IAAI,CAAA,oFAAA;AAAA,KAC5G;AAAA,EACJ;AACA,EAAA,MAAM,eAAA,CAAgB,KAAK,IAAI,CAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,YAAY,IAAI,CAAA;AAClC,EAAA,IAAI,CAAC,WAAA,CAAY,SAAS,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,uBAAA,CAAwB,IAAA,EAAM,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,QAAQ,SAAS,CAAA;AAC5B;AAMA,aAAA,EAAc;;;AC/Md,IAAM,uBAAuB,CAAC,KAAA,KAA0B,KAAA,CAAM,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAEhF,IAAM,aAAA,GAAgB,OAAO,MAAA,KAAsE;AAC/F,EAAA,MAAM,QAAQ,OAAO,MAAA,KAAW,UAAA,GAAa,MAAM,QAAO,GAAI,MAAA;AAC9D,EAAA,OAAO,KAAA,KAAU,UAAa,KAAA,KAAU,IAAA,IAAQ,UAAU,EAAA,GAAK,MAAA,GAAY,OAAO,KAAK,CAAA;AAC3F,CAAA;AAGA,IAAM,UAAA,GAAa,CAAC,IAAA,EAA0B,KAAA,KAC1C,KAAK,UAAA,KAAe,KAAA,CAAM,UAAA,IAAc,IAAA,CAAK,SAAA,KAAc,KAAA,CAAM,SAAA,IAAa,IAAA,CAAK,gBAAgB,KAAA,CAAM,WAAA;AAE7G,IAAM,UAAA,GAAa,CAAC,IAAA,EAA0B,KAAA,KAAuC,UAAA,CAAW,MAAM,KAAK,CAAA,IAAK,IAAA,CAAK,MAAA,KAAW,KAAA,CAAM,MAAA;AAOtI,IAAM,UAAA,GAAa,CAAC,IAAA,EAAoC,KAAA,KAAiD,OAAO,SAAS,UAAA,IAAc,OAAO,KAAA,KAAU,UAAA,IAAc,IAAA,KAAS,KAAA;AAQ/K,IAAM,aAAA,GAAgB,CAAC,MAAA,EAA4B,WAAA,KAAmC;AAClF,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,IAAA,EAAM;AAC/C,IAAA,MAAM,IAAI,KAAA,CAAM,eAAA,CAAgB,MAAA,EAAQ,WAAW,CAAC,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,QAAA,GAAW,eAAe,MAAM,CAAA;AACtC,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA,CAAM,oBAAA,CAAqB,QAAA,EAAU,WAAW,CAAC,CAAA;AAAA,EAC/D;AACA,EAAA,IAAI,MAAA,CAAO,gBAAgB,MAAA,IAAa,MAAA,CAAO,gBAAgB,IAAA,IAAQ,OAAO,MAAA,CAAO,WAAA,KAAgB,QAAA,EAAU;AAC3G,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,EAAG,MAAM,CAAA,uCAAA,EAA0C,OAAO,OAAO,WAAW,CAAA,8JAAA;AAAA,KAChF;AAAA,EACJ;AACJ,CAAA;AAGA,IAAM,eAAA,GAAkB,CAAC,MAAA,KAAqC;AAC1D,EAAA,IAAI,OAAO,OAAO,WAAA,KAAgB,QAAA,IAAY,OAAO,WAAA,CAAY,IAAA,OAAW,EAAA,EAAI;AAC5E,IAAA,OAAA,CAAQ,IAAA;AAAA,MACJ,GAAG,MAAM,CAAA,+OAAA;AAAA,KACb;AAAA,EACJ;AACJ,CAAA;AAOA,IAAM,YAAA,GAAe,CAAC,MAAA,KAAuC;AACzD,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,MAAA,CAAO,SAAS,CAAA;AACrD,EAAA,OAAO,MAAA,CAAO,WAAA,GAAc,CAAA,WAAA,EAAc,SAAS,CAAA,CAAA,EAAI,kBAAA,CAAmB,MAAA,CAAO,WAAW,CAAC,CAAA,CAAA,GAAK,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA;AAClI,CAAA;AAEA,IAAM,WAAA,GAAc,OAAO,MAAA,KAAgD;AACvE,EAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAS,GAAI,UAAA,EAAW;AAC3C,EAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,CAAgB,EAAE,cAAc,SAAA,EAAW,WAAA,EAAa,UAAU,CAAA;AAEpF,EAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,MAAA,CAAO,MAAM,CAAA;AAChD,EAAA,IAAI,MAAA,EAAQ;AACR,IAAA,KAAA,CAAM,GAAA,CAAI,aAAa,MAAM,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,CAAA,EAAG,oBAAA,CAAqB,MAAA,CAAO,UAAU,CAAC,CAAA,EAAG,YAAA,CAAa,MAAM,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,QAAA,EAAU,CAAA,CAAA;AAChG,CAAA;AAMA,IAAM,UAAA,GAAa,CAAC,MAAA,EAAgB,MAAA,KAAuC;AACvE,EAAA,IAAI,WAAW,GAAA,EAAK;AAChB,IAAA,MAAM,cAAc,MAAA,CAAO,WAAA,GACrB,CAAA,iBAAA,EAAoB,MAAA,CAAO,WAAW,CAAA,sBAAA,CAAA,GACtC,qHAAA;AACN,IAAA,OAAO;;AAAA,8FAAA,EAAqG,MAAA,CAAO,SAAS,CAAA,uCAAA,EAA0C,WAAW,CAAA,sGAAA,CAAA;AAAA,EACrL;AACA,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AAClC,IAAA,OAAO;;AAAA,4DAAA,EAAmE,OAAO,SAAS,CAAA,qGAAA,CAAA;AAAA,EAC9F;AACA,EAAA,OAAO,EAAA;AACX,CAAA;AAEA,IAAM,aAAA,GAAgB,OAAO,MAAA,KAAkD;AAC3E,EAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,MAAM,CAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,SAAS,EAAE,MAAA,EAAQ,kBAAA,EAAmB,EAAG,CAAA;AAC7E,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACd,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,kCAAA,EAAqC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,QAAA,CAAS,UAAU,CAAA,MAAA,EAAS,GAAG,CAAA,EAAG,UAAA,CAAW,SAAS,MAAA,EAAQ,MAAM,CAAC,CAAA,CAAE,CAAA;AAAA,EAC5J;AACA,EAAA,MAAM,OAAA,GAAW,MAAM,QAAA,CAAS,IAAA,EAAK;AACrC,EAAA,OAAO;AAAA,IACH,eAAA,EAAiB,OAAA,EAAS,eAAA,IAAmB,EAAC;AAAA,IAC9C,cAAA,EAAgB,OAAA,EAAS,cAAA,IAAkB;AAAC,GAChD;AACJ,CAAA;AAgBO,IAAM,SAAA,GAAY,CAAC,MAAA,KAAqC;AAC3D,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,aAAA,EAAc;AACd,EAAA,aAAA,CAAc,MAAA,EAAQ,MAAM,WAAW,CAAA;AACvC,EAAA,MAAM,UAAU,KAAA,CAAM,MAAA;AACtB,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,IAAI,CAAC,UAAA,CAAW,OAAA,EAAS,MAAM,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,IAAA;AAAA,QACJ,UAAA,CAAW,SAAS,MAAM,CAAA,GACpB,GAAG,MAAM,CAAA,wSAAA,CAAA,GACT,CAAA,EAAG,MAAM,CAAA,qFAAA,EAAwF,IAAA,CAAK,UAAU,EAAE,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,SAAA,EAAW,OAAA,CAAQ,WAAW,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAa,CAAC,CAAA,CAAA;AAAA,OAC7N;AAAA,IACJ;AACA,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,MAAA,EAAO;AAC3B,EAAA,eAAA,CAAgB,MAAM,CAAA;AACtB,EAAA,cAAA,EAAe;AACnB;AA0BO,IAAM,SAAA,GAAY,CAAC,MAAA,KAA+C;AACrE,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,UAAU,KAAA,CAAM,MAAA;AACtB,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,oBAAA,CAAqB,aAAA,EAAe,KAAA,CAAM,WAAW,CAAC,CAAA;AAAA,EAC1E;AACA,EAAA,IAAI,UAAA,CAAW,OAAA,CAAQ,MAAA,EAAQ,MAAM,CAAA,EAAG;AACpC,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,OAAA,EAAS,MAAA,EAAO;AACpC,EAAA,KAAA,CAAM,eAAA,GAAkB,IAAA;AAC5B;AAOO,IAAM,mBAAA,GAAsB,CAAC,WAAA,KAAmC;AACnE,EAAA,QAAA,GAAW,WAAA,GAAc,WAAA;AAC7B;AAWA,IAAM,YAAA,GAAe,CAAC,MAAA,KAAsC;AACxD,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,EAAA,IAAI,CAAC,MAAA,EAAQ;AAET,IAAA,OAAO,OAAA,CAAQ,OAAO,IAAI,KAAA,CAAM,qBAAqB,MAAA,EAAQ,KAAA,CAAM,WAAW,CAAC,CAAC,CAAA;AAAA,EACpF;AACA,EAAA,IAAI,CAAC,MAAM,eAAA,EAAiB;AAGxB,IAAA,MAAM,OAAA,GAAU,cAAc,MAAM,CAAA;AACpC,IAAA,KAAA,CAAM,eAAA,GAAkB,OAAA;AAIxB,IAAA,OAAA,CAAQ,MAAM,MAAM;AAChB,MAAA,IAAI,KAAA,CAAM,oBAAoB,OAAA,EAAS;AACnC,QAAA,KAAA,CAAM,eAAA,GAAkB,IAAA;AAAA,MAC5B;AAAA,IACJ,CAAC,CAAA;AAAA,EACL;AACA,EAAA,OAAO,KAAA,CAAM,eAAA;AACjB,CAAA;AAGO,IAAM,QAAA,GAAW,MAAyB,YAAA,CAAa,YAAY;AAQnE,IAAM,SAAA,GAAY,OAAO,IAAA,KAAkC;AAC9D,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAM,YAAA,CAAa,CAAA,WAAA,EAAc,IAAI,CAAA,EAAA,CAAI,CAAA;AACpE,EAAA,MAAM,QAAQ,cAAA,CAAe,IAAA,CAAK,CAAA,aAAA,KAAiB,aAAA,CAAc,SAAS,IAAI,CAAA;AAC9E,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,GAAA,CAAI,CAAA,aAAA,KAAiB,CAAA,CAAA,EAAI,cAAc,IAAI,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAC1F,IAAA,MAAM,WAAA,GAAc,QAAA,EAAS,CAAE,MAAA,EAAQ,WAAA;AAEvC,IAAA,MAAM,KAAA,GAAQ,WAAA,GAAc,CAAA,aAAA,EAAgB,WAAW,CAAA,CAAA,CAAA,GAAM,2CAAA;AAC7D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,6BAAA,EAAgC,IAAI,CAAA,gBAAA,EAAmB,KAAK,CAAA,EAAA,EAAK,SAAA,IAAa,gDAAgD,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9J;AACA,EAAA,IAAI,CAAC,MAAM,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,oBAAA,EAAuB,IAAI,CAAA,6EAAA,CAA+E,CAAA;AAAA,EACvI;AACA,EAAA,OAAO,KAAA,CAAM,GAAA;AACjB;AAGO,IAAM,kBAAkB,YAA6C;AACxE,EAAA,MAAM,EAAE,eAAA,EAAiB,SAAA,EAAU,GAAI,MAAM,aAAa,mBAAmB,CAAA;AAC7E,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAC9B,IAAA,IAAI,QAAA,IAAY,OAAO,QAAA,CAAS,GAAA,KAAQ,QAAA,EAAU;AAC9C,MAAA,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,GAAI,QAAA,CAAS,KAAA;AAAA,IACpC;AAAA,EACJ;AACA,EAAA,OAAO,MAAA;AACX;AAMO,IAAM,aAAa,MAAkB;AACxC,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AACnB,IAAA,KAAA,CAAM,aAAa,cAAA,EAAe;AAAA,EACtC;AACA,EAAA,OAAO,KAAA,CAAM,UAAA;AACjB","file":"index.js","sourcesContent":["/**\n * Everything the client says when its configuration is wrong or absent.\n *\n * The two required options almost always arrive from build time environment variables, so the\n * failure the host sees is not \"a value is invalid\" but \"nothing reached the bundle\". Messages here\n * are written for that moment: they name the option, show what actually arrived, say where the real\n * value comes from, and print the exact call to write, in the flavour of the package the host uses.\n */\n\nexport const PREFIX = \"[@mfe-orchestrator-hub/client]\"\n\n/** Which package the host went through. Only decides which snippet an error prints. */\nexport type Integration = \"core\" | \"react\" | \"vue\" | \"angular\"\n\n/** The two options without which nothing can be requested. */\nexport type RequiredOption = \"backendUrl\" | \"projectId\"\n\nconst EXAMPLE_BACKEND_URL = \"https://console.mfe-orchestrator.dev/api\"\nconst EXAMPLE_PROJECT_ID = \"6f1b2c3d4e5f6a7b8c9d0e1f\"\n\nconst SNIPPETS: Record<Integration, string> = {\n core: `import { configure } from \"@mfe-orchestrator-hub/client\"\n\nconfigure({\n backendUrl: \"${EXAMPLE_BACKEND_URL}\",\n projectId: \"${EXAMPLE_PROJECT_ID}\"\n})`,\n react: `import { OrchestratorProvider } from \"@mfe-orchestrator-hub/client-react\"\n\n<OrchestratorProvider config={{ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }}>\n <App />\n</OrchestratorProvider>`,\n vue: `import { createOrchestrator } from \"@mfe-orchestrator-hub/client-vue\"\n\napp.use(createOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" }))`,\n angular: `import { provideOrchestrator } from \"@mfe-orchestrator-hub/client-angular\"\n\nbootstrapApplication(AppComponent, {\n providers: [provideOrchestrator({ backendUrl: \"${EXAMPLE_BACKEND_URL}\", projectId: \"${EXAMPLE_PROJECT_ID}\" })]\n})`\n}\n\nconst WHERE: Record<Integration, string> = {\n core: \"Call it once, at the very top of the host entry point, before anything imports a remote.\",\n react: \"Render it above every component that resolves a remote. Better still, call configure() at the very top of the entry point: a bundler may import a remote before React mounts.\",\n vue: \"Install the plugin before mounting the app. Better still, call configure() at the very top of the entry point: a bundler may import a remote before the app is created.\",\n angular: \"Pass it to bootstrapApplication(). Better still, call configure() at the very top of main.ts: a lazily loaded remote must find the client already configured.\"\n}\n\nconst WHAT_IT_IS: Record<RequiredOption, string> = {\n backendUrl: `It is the base URL of the console API, protocol included, ex. \"${EXAMPLE_BACKEND_URL}\". A path on the same origin as the host, ex. \"/api\", works too.`,\n projectId: `It is the id of the project in the console: open the project and copy it from its page, ex. \"${EXAMPLE_PROJECT_ID}\".`\n}\n\n/** The name the value travels under from the bundler config into the bundle, per toolchain. */\nconst BUILD_VARIABLE: Record<RequiredOption, { vite: string; webpack: string }> = {\n backendUrl: { vite: \"VITE_MFE_BACKEND_URL\", webpack: \"MFE_BACKEND_URL\" },\n projectId: { vite: \"VITE_MFE_PROJECT_ID\", webpack: \"MFE_PROJECT_ID\" }\n}\n\n/**\n * What an option that was never substituted into the bundle looks like.\n *\n * The bundler config is named before the .env file on purpose: it is where the console writes both\n * values when it generates the config, so it is where they are missing from when they are missing.\n */\nconst missingEnvHint = (option: RequiredOption): string =>\n `Nothing arrived here at all, which is what a value that never reached the bundle looks like: check ${BUILD_VARIABLE[option].vite} (Vite) or ${BUILD_VARIABLE[option].webpack} (webpack) in the build that produced this bundle. The generated configs carry it in the \"define\" block of vite.config, or in the DefinePlugin of webpack.config, so look there first; declared only in a .env file the build never reads, it looks exactly like this.`\n\n/** Values that mean \"the template was never filled in\". */\nconst PLACEHOLDER = /^(…|\\.{3}|undefined|null|nan|<[^>]*>|\\{\\{[^}]*\\}\\}|\\$\\{[^}]*\\}|your[-_ ]?[a-z]*|x{3,}|change[-_ ]?me|todo|tbd)$/i\n\n/** Long values are cut: an error message is not the place to print a whole JWT. */\nconst quoted = (value: string): string => JSON.stringify(value.length > 120 ? `${value.slice(0, 120)}…` : value)\n\nconst described = (value: unknown): string => {\n if (value === null) {\n return \"null\"\n }\n if (Array.isArray(value)) {\n return \"an array\"\n }\n const type = typeof value\n return type === \"object\" || type === \"function\" ? `a ${type}` : `a ${type} (${String(value)})`\n}\n\n/** Same key modulo case and separators: projectID, project_id, PROJECT-ID all collapse onto projectid. */\nconst normalized = (key: string): string => key.toLowerCase().replace(/[^a-z0-9]/g, \"\")\n\nconst ALIASES: Record<RequiredOption, string[]> = {\n backendUrl: [\"backendurl\", \"backendbaseurl\", \"apiurl\", \"baseurl\", \"consoleurl\", \"url\", \"backend\"],\n projectId: [\"projectid\", \"project\", \"idproject\", \"projectuuid\", \"projectkey\"]\n}\n\n/**\n * The key the host actually wrote, when it looks like a misspelling of the one that is missing.\n * `projectID` is by far the most common: it is silently ignored, so without this the message would\n * claim the option is absent while the developer stares at a line that clearly sets it.\n */\nconst confusableKey = (option: RequiredOption, config: unknown): string | undefined => {\n if (typeof config !== \"object\" || config === null) {\n return undefined\n }\n const candidates = ALIASES[option]\n return Object.keys(config).find(key => key !== option && candidates.includes(normalized(key)))\n}\n\n/** One thing that is wrong with one option, already spelled out. */\nexport interface ConfigProblem {\n option: RequiredOption\n /** Predicate completing \"<option> …\", ex. `is missing`. */\n what: string\n /** Extra lines, printed under the option, that say how to fix this particular case. */\n hints: string[]\n}\n\nconst problem = (option: RequiredOption, what: string, ...hints: (string | undefined)[]): ConfigProblem => ({\n option,\n what,\n hints: [WHAT_IT_IS[option], ...hints].filter((hint): hint is string => Boolean(hint))\n})\n\n/**\n * A backendUrl the client can actually build a request on: an absolute http(s) URL, or a path on the\n * host's own origin, which `fetch` resolves against the page.\n */\nconst diagnoseBackendUrl = (value: string): ConfigProblem | null => {\n const trimmed = value.trim()\n if (trimmed.startsWith(\"/\")) {\n return null\n }\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, which is not a URL`,\n trimmed.includes(\".\") || trimmed.includes(\":\")\n ? `It looks like a host without a protocol: write \"https://${trimmed}\" instead, or \"/${trimmed.replace(/^\\/+/, \"\")}\" if the console API answers on the same origin as this page.`\n : undefined\n )\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return problem(\n \"backendUrl\",\n `is ${quoted(value)}, whose \"${parsed.protocol.replace(\":\", \"\")}\" scheme is neither http nor https`,\n 'A bare \"host:port\" is read as a scheme: write \"http://localhost:3000/api\", not \"localhost:3000/api\".'\n )\n }\n return null\n}\n\n/** Everything wrong with one required option, or null when it is usable. */\nconst diagnose = (option: RequiredOption, config: unknown): ConfigProblem | null => {\n const value = (config as Record<string, unknown> | null | undefined)?.[option]\n const typo = confusableKey(option, config)\n const typoHint = typo ? `The configuration carries \"${typo}\", which the client ignores. The option is spelled \"${option}\".` : undefined\n\n if (value === undefined || value === null) {\n return problem(option, value === null ? \"is null\" : \"is missing\", typoHint, typo ? undefined : missingEnvHint(option))\n }\n if (typeof value !== \"string\") {\n return problem(option, `is ${described(value)}, not a string`, typoHint)\n }\n if (value.trim() === \"\") {\n return problem(option, value === \"\" ? \"is an empty string\" : \"holds nothing but whitespace\", typoHint, missingEnvHint(option))\n }\n if (PLACEHOLDER.test(value.trim())) {\n const looksLikeAnUnsetVariable = /^(undefined|null|nan)$/i.test(value.trim())\n return problem(option, `is still the placeholder ${quoted(value)}`, typoHint, looksLikeAnUnsetVariable ? missingEnvHint(option) : undefined)\n }\n if (option === \"projectId\" && value.trim() !== value) {\n // Percent encoded into the path, so the padding would travel to the backend as %20.\n return problem(\n \"projectId\",\n `is ${quoted(value)}, padded with whitespace`,\n \"Trim the value: it is percent encoded into the manifest URL, so the spaces would reach the backend as part of the id.\"\n )\n }\n return option === \"backendUrl\" ? diagnoseBackendUrl(value) : null\n}\n\n/** Every problem of a configuration, in the order the options are declared. Empty means usable. */\nexport const diagnoseConfig = (config: unknown): ConfigProblem[] =>\n ([\"backendUrl\", \"projectId\"] as const).map(option => diagnose(option, config)).filter((found): found is ConfigProblem => found !== null)\n\nconst bulleted = (problems: ConfigProblem[]): string => problems.map(({ option, what, hints }) => [` • ${option} ${what}.`, ...hints.map(hint => ` → ${hint}`)].join(\"\\n\")).join(\"\\n\")\n\nconst indented = (block: string): string =>\n block\n .split(\"\\n\")\n .map(line => (line ? ` ${line}` : line))\n .join(\"\\n\")\n\nconst howToConfigure = (integration: Integration): string => `Configure the client like this:\\n\\n${indented(SNIPPETS[integration])}\\n\\n${WHERE[integration]}`\n\nconst listed = (options: RequiredOption[]): string => (options.length > 1 ? `${options.slice(0, -1).join(\", \")} and ${options.at(-1)}` : String(options[0]))\n\n/** The message thrown by `configure()` when what it received cannot be used. */\nexport const invalidConfigMessage = (problems: ConfigProblem[], integration: Integration): string => {\n const options = problems.map(({ option }) => option)\n const headline = `${PREFIX} configure() cannot start the client: ${listed(options)} ${options.length > 1 ? \"are\" : \"is\"} not usable.`\n return `${headline}\\n\\n${bulleted(problems)}\\n\\n${howToConfigure(integration)}`\n}\n\n/** The message thrown by `configure()` when it did not even receive an object. */\nexport const noConfigMessage = (config: unknown, integration: Integration): string =>\n `${PREFIX} configure() was called with ${config === undefined ? \"no argument\" : described(config)} instead of a configuration object. It needs at least backendUrl and projectId.\\n\\n${howToConfigure(integration)}`\n\n/** The message every read rejects with while the client has no configuration at all. */\nexport const notConfiguredMessage = (caller: string, integration: Integration): string =>\n `${PREFIX} the client is not configured: ${caller} was called before configure() ever ran, so neither backendUrl nor projectId is known and no manifest can be requested.\\n\\n${howToConfigure(integration)}`\n","import type { Integration } from \"./errors\"\nimport type { Identities, Manifest, OrchestratorConfig, WebpackContainer } from \"./types\"\n\nexport interface OrchestratorState {\n config: OrchestratorConfig | null\n manifestPromise: Promise<Manifest> | null\n identities: Identities | null\n /** Set by the framework adapters as they load, so an error prints the snippet of their own API. */\n integration: Integration\n // The webpack remote loader's state, below. Optional because a slot created by an older copy of\n // this package on the same page has none of it: each field is filled in on first use.\n /** Settled by the first `configure()`, so a remote requested earlier can wait for it. */\n configured?: { promise: Promise<void>; resolve: () => void }\n /** One script load per remote entry URL, shared by every caller asking for it. */\n remoteEntries?: Map<string, Promise<void>>\n /** One guarded proxy per container, so the guard holds however many times it is resolved. */\n containers?: WeakMap<WebpackContainer, WebpackContainer>\n}\n\n/**\n * The state lives on `globalThis` under this key, not in a module scope variable.\n *\n * A host can end up with two copies of this package loaded at once: the app imports the ESM build\n * while something else pulls the CJS one, or the bundler config and the app resolve to different\n * chunks. Two module scopes would mean two configurations and two manifest requests, which is\n * exactly what the contract forbids. One well known global slot makes the singleton real.\n */\nexport const STATE_KEY = \"__mfe_orchestrator_client__\"\n\nconst globalSlot = globalThis as typeof globalThis & Record<typeof STATE_KEY, OrchestratorState | undefined>\n\nexport const getState = (): OrchestratorState => {\n let state = globalSlot[STATE_KEY]\n if (!state) {\n state = { config: null, manifestPromise: null, identities: null, integration: \"core\" }\n globalSlot[STATE_KEY] = state\n }\n return state\n}\n","import type { Identities } from \"./types\"\n\nexport const SESSION_ID_KEY = \"mfe-orchestrator.sessionId\"\nexport const DEVICE_ID_KEY = \"mfe-orchestrator.deviceId\"\n\nconst PROBE_KEY = \"mfe-orchestrator.probe\"\n\ntype StorageKind = \"local\" | \"session\"\n\n/**\n * Ids minted while storage was unusable. They live for the lifetime of the page so that, even\n * without storage, every request of this page load carries one stable pair of ids.\n */\nconst inMemoryIds = new Map<string, string>()\n\nconst uuidFromRandomBytes = (bytes: Uint8Array): string => {\n bytes[6] = (bytes[6] & 0x0f) | 0x40\n bytes[8] = (bytes[8] & 0x3f) | 0x80\n const hex: string[] = []\n for (const byte of bytes) {\n hex.push(byte.toString(16).padStart(2, \"0\"))\n }\n return `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`\n}\n\n/**\n * A v4 UUID. `crypto.randomUUID` is the intended path; the two fallbacks only exist so that a page\n * served over plain http, or an exotic runtime, still gets an id instead of an exception.\n */\nexport const newId = (): string => {\n const cryptoApi = globalThis.crypto\n try {\n if (typeof cryptoApi?.randomUUID === \"function\") {\n return cryptoApi.randomUUID()\n }\n if (typeof cryptoApi?.getRandomValues === \"function\") {\n return uuidFromRandomBytes(cryptoApi.getRandomValues(new Uint8Array(16)))\n }\n } catch {\n // fall through to the non cryptographic fallback\n }\n const bytes = new Uint8Array(16)\n for (let index = 0; index < bytes.length; index++) {\n bytes[index] = Math.floor(Math.random() * 256)\n }\n return uuidFromRandomBytes(bytes)\n}\n\n/**\n * The requested storage, or `null` when it is missing or unusable.\n *\n * Both the property access and the write can throw: Safari in private mode exposes the object and\n * then refuses `setItem`, some hardened browsers throw a SecurityError on the access itself. The\n * write probe is the only reliable way to tell a usable storage from a decorative one.\n */\nconst openStorage = (kind: StorageKind): Storage | null => {\n try {\n const storage = kind === \"local\" ? globalThis.localStorage : globalThis.sessionStorage\n if (!storage) {\n return null\n }\n storage.setItem(PROBE_KEY, \"1\")\n storage.removeItem(PROBE_KEY)\n return storage\n } catch {\n return null\n }\n}\n\n/**\n * The id under `key`, read from storage and created on first use. Falls back to an id kept in\n * memory when storage cannot be used, so this never throws out of the SDK.\n */\nconst persistentId = (kind: StorageKind, key: string): string => {\n const storage = openStorage(kind)\n if (storage) {\n try {\n const stored = storage.getItem(key)\n if (stored) {\n return stored\n }\n const created = newId()\n storage.setItem(key, created)\n return created\n } catch {\n // storage passed the probe and failed anyway: keep going with an in memory id\n }\n }\n const remembered = inMemoryIds.get(key)\n if (remembered) {\n return remembered\n }\n const created = newId()\n inMemoryIds.set(key, created)\n return created\n}\n\n/** Reads, and creates when needed, the session and device ids. */\nexport const readIdentities = (): Identities => ({\n sessionId: persistentId(\"session\", SESSION_ID_KEY),\n deviceId: persistentId(\"local\", DEVICE_ID_KEY)\n})\n","import { notConfiguredMessage, PREFIX } from \"./errors\"\nimport { manifest, remoteUrl } from \"./index\"\nimport { getState, type OrchestratorState } from \"./state\"\nimport type { WebpackContainer } from \"./types\"\n\n/**\n * The global the webpack config reaches the client through.\n *\n * A `promise` remote of ModuleFederationPlugin is an expression pasted verbatim into the host\n * bundle, outside of any module, so it cannot import this package: a bare `import()` there reaches\n * the browser untouched and fails to resolve. A well known global is the one thing such an\n * expression can always read, hence `promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote(…)`.\n */\nexport const GLOBAL_NAMESPACE = \"__MFE_ORCHESTRATOR__\"\n\n/** What the global namespace carries. Only ever extended, so an older config keeps working. */\nexport interface OrchestratorGlobal {\n loadWebpackRemote: typeof loadWebpackRemote\n}\n\n/**\n * How long a remote requested before `configure()` waits for it. Long enough for a host that\n * configures after an async step of its own, short enough to turn a configure() that will never run\n * into an error rather than a page that hangs.\n */\nexport const CONFIGURE_TIMEOUT_MS = 10_000\n\nconst globalScope = globalThis as unknown as Record<string, unknown>\n\n/**\n * Puts the loader on the global namespace. Run when the module loads, so a remote requested before\n * `configure()` finds it, and again by `configure()`, in case a bundler dropped the top level call\n * believing the module free of side effects. The first copy of the package to publish keeps the\n * slot: every copy reads the same global state, so they are interchangeable.\n */\nexport const publishGlobal = (): void => {\n const existing = globalScope[GLOBAL_NAMESPACE] as Partial<OrchestratorGlobal> | undefined\n const namespace: Partial<OrchestratorGlobal> = existing ?? {}\n if (typeof namespace.loadWebpackRemote !== \"function\") {\n namespace.loadWebpackRemote = loadWebpackRemote\n }\n globalScope[GLOBAL_NAMESPACE] = namespace\n}\n\nconst configuredSignal = (state: OrchestratorState): NonNullable<OrchestratorState[\"configured\"]> => {\n if (!state.configured) {\n let resolve = (): void => {}\n const promise = new Promise<void>(settle => {\n resolve = settle\n })\n state.configured = { promise, resolve }\n }\n return state.configured\n}\n\n/** Called by `configure()` once it stored a configuration: releases every remote waiting for it. */\nexport const markConfigured = (): void => {\n configuredSignal(getState()).resolve()\n}\n\n/**\n * Resolves once the client is configured. Waiting rather than rejecting right away is what lets a\n * host configure after a step of its own, but only for so long: a remote imported by the very chunk\n * that calls `configure()` makes webpack load the remote before that chunk ever runs, and that\n * would otherwise hang the page forever.\n */\nconst whenConfigured = (caller: string): Promise<void> => {\n const state = getState()\n if (state.config) {\n return Promise.resolve()\n }\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(\n new Error(\n `${notConfiguredMessage(caller, state.integration)}\\n\\nThe remote waited ${CONFIGURE_TIMEOUT_MS / 1000} seconds for it. With webpack, call configure() in the entry file and load the rest of the app with import(\"./bootstrap\") after it: a remote imported by the chunk that calls configure() is loaded before that chunk runs, so it can never see the configuration.`\n )\n )\n }, CONFIGURE_TIMEOUT_MS)\n configuredSignal(state).promise.then(() => {\n clearTimeout(timer)\n resolve()\n })\n })\n}\n\n/**\n * Injects the remote entry script once per URL. Concurrent and later callers share the same load. A\n * failed load is forgotten, like a failed manifest, so the next caller tries again instead of\n * inheriting a rejection for the rest of the page load.\n */\nconst loadRemoteEntry = (url: string, slug: string): Promise<void> => {\n const state = getState()\n state.remoteEntries ??= new Map()\n const entries = state.remoteEntries\n const known = entries.get(url)\n if (known) {\n return known\n }\n const load = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(new Error(`${PREFIX} loadWebpackRemote(\"${slug}\") needs a browser document to load ${url} into, and there is none here.`))\n return\n }\n const script = document.createElement(\"script\")\n script.src = url\n script.async = true\n script.onload = () => resolve()\n script.onerror = () => {\n script.remove()\n reject(\n new Error(\n `${PREFIX} the remote entry of \"${slug}\" failed to load from ${url}. The browser gives no reason for a failed script, so open the URL in a tab or look at the network panel: a 404 means the served version has no file at that path, a blocked request usually means a Content-Security-Policy (script-src) or a mixed content rule.`\n )\n )\n }\n document.head.appendChild(script)\n })\n entries.set(url, load)\n load.catch(() => {\n if (entries.get(url) === load) {\n entries.delete(url)\n }\n })\n return load\n}\n\nconst isContainer = (value: unknown): value is WebpackContainer =>\n typeof value === \"object\" && value !== null && typeof (value as WebpackContainer).get === \"function\" && typeof (value as WebpackContainer).init === \"function\"\n\n/** Global names holding something shaped like a container, to point at the name the remote really uses. */\nconst containerNames = (): string[] => {\n const names: string[] = []\n for (const key of Object.keys(globalScope)) {\n try {\n if (isContainer(globalScope[key])) {\n names.push(`\"${key}\"`)\n }\n } catch {\n // A getter on the global that throws is simply not a container.\n }\n }\n return names\n}\n\nconst missingContainerMessage = (slug: string, scope: string, url: string): string => {\n const found = containerNames()\n return `${PREFIX} the remote entry of \"${slug}\" loaded from ${url}, but globalThis[\"${scope}\"] is not a webpack container. The scope must be the name the remote passes to its own ModuleFederationPlugin, and the remote must keep its default library type (\"var\"). ${\n found.length > 0 ? `Containers on this page: ${found.join(\", \")}.` : \"No container is defined on this page at all.\"\n } A remote built with Vite is an ES module, not a webpack container, and cannot be loaded this way.`\n}\n\n/**\n * A `{ get, init }` passthrough that ignores every `init` after the first. A container may be\n * initialized only once: two hosts, or two remotes sharing a third, would otherwise both init it and\n * webpack throws on the second share scope. The later calls get the result of the first.\n */\nconst guarded = (container: WebpackContainer): WebpackContainer => {\n const state = getState()\n state.containers ??= new WeakMap()\n const known = state.containers.get(container)\n if (known) {\n return known\n }\n let initialized: { result: unknown } | null = null\n const proxy: WebpackContainer = {\n get: module => container.get(module),\n init: (shareScope, initScope) => {\n if (!initialized) {\n initialized = { result: container.init(shareScope, initScope) }\n }\n return initialized.result\n }\n }\n state.containers.set(container, proxy)\n return proxy\n}\n\n/**\n * What a webpack `promise` remote must resolve to: the container of the microfrontend, at the\n * version the backend serves this page.\n *\n * It resolves the URL with `remoteUrl(slug)`, injects that remote entry script once per URL, reads\n * the container off `globalThis[scope]` and returns a `{ get, init }` proxy whose `init` runs once.\n * Requested before `configure()`, it waits for it, up to `CONFIGURE_TIMEOUT_MS`.\n *\n * `scope` is the remote's own ModuleFederationPlugin `name`. Left out, it is the `nameToIntegrate`\n * of the microfrontend in the manifest, which is the name the console generates for it.\n *\n * Meant for the webpack config, through the global namespace, not for application code:\n *\n * remotes: {\n * checkoutnew: \"promise globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote('checkout-new', 'checkoutnew')\"\n * }\n */\nexport const loadWebpackRemote = async (slug: string, scope?: string): Promise<WebpackContainer> => {\n const caller = `loadWebpackRemote(\"${slug}\")`\n await whenConfigured(caller)\n const url = await remoteUrl(slug)\n const name = scope || (await manifest()).microfrontends.find(microfrontend => microfrontend.slug === slug)?.nameToIntegrate\n if (!name) {\n throw new Error(\n `${PREFIX} ${caller} has no scope: none was passed and the manifest gives no nameToIntegrate for \"${slug}\". Pass the name the remote gives its ModuleFederationPlugin as the second argument.`\n )\n }\n await loadRemoteEntry(url, slug)\n const container = globalScope[name]\n if (!isContainer(container)) {\n throw new Error(missingContainerMessage(slug, name, url))\n }\n return guarded(container)\n}\n\n// On load, not only in configure(): a webpack remote requested before configure() ran must find the\n// loader on the global namespace, and then waits for the configuration. It lives here rather than in\n// index.ts because the two modules import each other, and only this one is sure to have evaluated its\n// own exports by the time this line runs, whichever of the two is loaded first.\npublishGlobal()\n","import { diagnoseConfig, type Integration, invalidConfigMessage, noConfigMessage, notConfiguredMessage, PREFIX } from \"./errors\"\nimport { getState } from \"./state\"\nimport { readIdentities } from \"./storage\"\nimport type { Identities, Manifest, OrchestratorConfig } from \"./types\"\nimport { markConfigured, publishGlobal } from \"./webpack\"\n\nexport type { ConfigProblem, Integration } from \"./errors\"\nexport type { GlobalVariable, Identities, Manifest, Microfrontend, OrchestratorConfig, WebpackContainer } from \"./types\"\nexport { CONFIGURE_TIMEOUT_MS, GLOBAL_NAMESPACE, loadWebpackRemote, type OrchestratorGlobal } from \"./webpack\"\n\nconst withoutTrailingSlash = (value: string): string => value.replace(/\\/+$/, \"\")\n\nconst resolveUserId = async (userId: OrchestratorConfig[\"userId\"]): Promise<string | undefined> => {\n const value = typeof userId === \"function\" ? await userId() : userId\n return value === undefined || value === null || value === \"\" ? undefined : String(value)\n}\n\n/** Everything but the identity: the part of the configuration that is fixed for a page load. */\nconst sameTarget = (left: OrchestratorConfig, right: OrchestratorConfig): boolean =>\n left.backendUrl === right.backendUrl && left.projectId === right.projectId && left.environment === right.environment\n\nconst sameConfig = (left: OrchestratorConfig, right: OrchestratorConfig): boolean => sameTarget(left, right) && left.userId === right.userId\n\n/**\n * Whether replacing the identity would change nothing. Two getters are never considered equal, even the\n * same one twice: what a function returns is exactly what this side cannot know, so a host handing one\n * over is taken at its word and the manifest is re-fetched.\n */\nconst sameUserId = (left: OrchestratorConfig[\"userId\"], right: OrchestratorConfig[\"userId\"]): boolean => typeof left !== \"function\" && typeof right !== \"function\" && left === right\n\n/**\n * Rejects a configuration the client could not use, with a message that names the option, shows what\n * actually arrived and prints the call to write. environment is deliberately not required: without\n * it the backend resolves it from the domain. It is still checked for type, because a non string\n * there would silently end up percent encoded into the path.\n */\nconst requireConfig = (config: OrchestratorConfig, integration: Integration): void => {\n if (typeof config !== \"object\" || config === null) {\n throw new Error(noConfigMessage(config, integration))\n }\n const problems = diagnoseConfig(config)\n if (problems.length > 0) {\n throw new Error(invalidConfigMessage(problems, integration))\n }\n if (config.environment !== undefined && config.environment !== null && typeof config.environment !== \"string\") {\n throw new Error(\n `${PREFIX} configure() received environment as a ${typeof config.environment}, not a string. Pass the environment slug as it appears in the console, ex. \"DEV\", or leave it out to let the backend resolve it from the domain of this page.`\n )\n }\n}\n\n/** Notices about a stored configuration that works but probably does not do what the host meant. */\nconst warnAboutConfig = (config: OrchestratorConfig): void => {\n if (typeof config.environment === \"string\" && config.environment.trim() === \"\") {\n console.warn(\n `${PREFIX} configure() received an empty environment, so the client falls back to the auto routes and the backend resolves the environment from the domain of this page. Remove the option if that is what you want, or check the variable that feeds it.`\n )\n }\n}\n\n/**\n * Two shapes, one per route family. With an explicit environment the slug is the last segment; with\n * no environment the \"auto\" segment takes its place before the project id and the backend resolves\n * the environment from the domain the request comes from.\n */\nconst manifestPath = (config: OrchestratorConfig): string => {\n const projectId = encodeURIComponent(config.projectId)\n return config.environment ? `/serve/all/${projectId}/${encodeURIComponent(config.environment)}` : `/serve/all/auto/${projectId}`\n}\n\nconst manifestUrl = async (config: OrchestratorConfig): Promise<string> => {\n const { sessionId, deviceId } = identities()\n const query = new URLSearchParams({ mfeSessionId: sessionId, mfeDeviceId: deviceId })\n // Resolved as late as possible: the host may only know the user after its own auth round trip.\n const userId = await resolveUserId(config.userId)\n if (userId) {\n query.set(\"mfeUserId\", userId)\n }\n return `${withoutTrailingSlash(config.backendUrl)}${manifestPath(config)}?${query.toString()}`\n}\n\n/**\n * What a status usually means on this route. The backend answers the same 404 for an unknown project\n * and for an unknown environment, and the two are indistinguishable from here, so both are named.\n */\nconst statusHint = (status: number, config: OrchestratorConfig): string => {\n if (status === 404) {\n const environment = config.environment\n ? `the environment \"${config.environment}\" does not exist in it`\n : \"no environment of that project declares the domain this page is served on, which is what the auto route resolves on\"\n return `\\n\\nA 404 on this route means the backend did not find what the URL names: either the project id \"${config.projectId}\" is not a project of this console, or ${environment}. Check both in the console, and check that backendUrl points at the console API of the same instance.`\n }\n if (status === 401 || status === 403) {\n return `\\n\\nThe console refused the request. Check that the project id \"${config.projectId}\" belongs to the instance backendUrl points at, and that this domain is allowed to read its manifest.`\n }\n return \"\"\n}\n\nconst fetchManifest = async (config: OrchestratorConfig): Promise<Manifest> => {\n const url = await manifestUrl(config)\n // No retry in v1: whatever fetch throws travels straight to the caller.\n const response = await fetch(url, { headers: { accept: \"application/json\" } })\n if (!response.ok) {\n throw new Error(`${PREFIX} the manifest request failed with ${response.status} ${response.statusText}. GET ${url}${statusHint(response.status, config)}`)\n }\n const payload = (await response.json()) as Partial<Manifest> | null\n return {\n globalVariables: payload?.globalVariables ?? [],\n microfrontends: payload?.microfrontends ?? []\n }\n}\n\n/**\n * Hands the client its configuration. Call it once, synchronously, before any remote is imported.\n *\n * `backendUrl` and `projectId` are required. `environment` is not: omitting it makes the client use\n * the \"auto\" routes, where the backend resolves the environment from the domain of the host page.\n *\n * Idempotent: calling it again with the same options is a no op, so a framework provider may safely\n * call it on every render. A second call with different options is ignored, with a warning, because\n * the manifest of this page load may already be in flight or resolved. The user is the exception, and\n * it changes through `setUserId()`, not through a second call here.\n *\n * It also publishes `globalThis.__MFE_ORCHESTRATOR__.loadWebpackRemote`, which a webpack config\n * reaches the client through, and releases every webpack remote that was requested before it ran.\n */\nexport const configure = (config: OrchestratorConfig): void => {\n const state = getState()\n publishGlobal()\n requireConfig(config, state.integration)\n const current = state.config\n if (current) {\n if (!sameConfig(current, config)) {\n console.warn(\n sameTarget(current, config)\n ? `${PREFIX} configure() was called again with a different userId. The configuration is fixed for this page load, so this one is ignored: call setUserId() instead, which is the supported way to change the user mid session and also drops the memoized manifest, so the next read is decided on the new identity.`\n : `${PREFIX} configure() was called again with a different configuration. The first one is kept: ${JSON.stringify({ backendUrl: current.backendUrl, projectId: current.projectId, environment: current.environment })}.`\n )\n }\n return\n }\n state.config = { ...config }\n warnAboutConfig(config)\n markConfigured()\n}\n\n/**\n * Replaces the identity the backend decides a user based canary on, after the client was configured.\n *\n * `configure()` is deliberately once only, and this is the one option that legitimately changes while\n * the page is alive: a login, a logout, an account switch. So it gets its own setter, and that setter\n * does what `configure()` must not — it drops the memoized manifest, so the next `manifest()`,\n * `remoteUrl()` or `globalVariables()` asks the backend again and is answered for the new user.\n *\n * Pass `undefined` on logout: the next request then carries no `mfeUserId` at all, which is what makes\n * the backend hand out the stable version again.\n *\n * What this does NOT do is reload the remotes already imported. The federation runtime keeps the\n * container it has, so a microfrontend already on the page stays on the version drawn for the previous\n * user, and only remotes resolved after this call see the new one. When the whole page must be\n * consistent, follow the identity change with a reload; when the host mounts its remotes behind its own\n * auth guard, calling this before the guard opens is enough.\n *\n * Setting the same plain value again is a no op, so an auth store may call it on every emission without\n * costing a request. A getter is always taken as a change, since what it returns is precisely what this\n * side cannot know.\n *\n * A request already in flight is not cancelled: whoever is awaiting it still receives the manifest of\n * the previous identity. Only the memo is dropped.\n */\nexport const setUserId = (userId: OrchestratorConfig[\"userId\"]): void => {\n const state = getState()\n const current = state.config\n if (!current) {\n throw new Error(notConfiguredMessage(\"setUserId()\", state.integration))\n }\n if (sameUserId(current.userId, userId)) {\n return\n }\n state.config = { ...current, userId }\n state.manifestPromise = null\n}\n\n/**\n * @internal Lets a framework adapter say which package the host is really using, so a configuration\n * error prints the snippet of that API instead of the bare `configure()` one. Idempotent, and never\n * needed by an application: the adapters call it as they load.\n */\nexport const registerIntegration = (integration: Integration): void => {\n getState().integration = integration\n}\n\n/**\n * The whole manifest of the environment, fetched once per page load and memoized as a promise, so\n * that concurrent callers share the single request in flight.\n *\n * A successful result is memoized for good. A failed attempt is not: the memo is dropped when the\n * shared attempt settles as rejected, so the next caller starts a fresh request. That is not a retry\n * — nothing here loops or backs off — it only means one flaky lookup at boot does not condemn the\n * page to reject every `remoteUrl()` until a full reload.\n */\nconst loadManifest = (caller: string): Promise<Manifest> => {\n const state = getState()\n const config = state.config\n if (!config) {\n // Not memoized: the host may still configure the client and try again.\n return Promise.reject(new Error(notConfiguredMessage(caller, state.integration)))\n }\n if (!state.manifestPromise) {\n // Assigned before the first await inside fetchManifest, which is what makes N concurrent\n // callers collapse onto one request.\n const attempt = fetchManifest(config)\n state.manifestPromise = attempt\n // Cleared once, when the shared attempt settles, not in each caller's own catch: every\n // caller already waiting on this attempt still gets its rejection. The identity check keeps\n // a late failure from evicting a newer attempt.\n attempt.catch(() => {\n if (state.manifestPromise === attempt) {\n state.manifestPromise = null\n }\n })\n }\n return state.manifestPromise\n}\n\n/** The whole manifest of the environment. See `loadManifest` for the memoization contract. */\nexport const manifest = (): Promise<Manifest> => loadManifest(\"manifest()\")\n\n/**\n * The ready to use, version pinned URL of a remote. Awaits the manifest internally.\n *\n * The returned URL is used verbatim: the host never parses the version out of it and never strips\n * the `_v/<version>/` segment, or a classic script would load its chunks off another version.\n */\nexport const remoteUrl = async (slug: string): Promise<string> => {\n const { microfrontends } = await loadManifest(`remoteUrl(\"${slug}\")`)\n const found = microfrontends.find(microfrontend => microfrontend.slug === slug)\n if (!found) {\n const available = microfrontends.map(microfrontend => `\"${microfrontend.slug}\"`).join(\", \")\n const environment = getState().config?.environment\n // With no configured environment the host cannot name the one it was served: only the backend knows.\n const where = environment ? `environment \"${environment}\"` : \"the environment resolved from this domain\"\n throw new Error(`${PREFIX} unknown microfrontend slug \"${slug}\". Available in ${where}: ${available || \"none, this environment serves no microfrontend\"}.`)\n }\n if (!found.url) {\n throw new Error(`${PREFIX} the microfrontend \"${slug}\" is in the manifest but carries no url. Check its deployment in the console.`)\n }\n return found.url\n}\n\n/** The global variables of the environment, as a plain object. */\nexport const globalVariables = async (): Promise<Record<string, string>> => {\n const { globalVariables: variables } = await loadManifest(\"globalVariables()\")\n const result: Record<string, string> = {}\n for (const variable of variables) {\n if (variable && typeof variable.key === \"string\") {\n result[variable.key] = variable.value\n }\n }\n return result\n}\n\n/**\n * The session and device ids of this page, exposed for telemetry and debugging. Created on first\n * use and stable for the lifetime of the page, whether or not storage is available.\n */\nexport const identities = (): Identities => {\n const state = getState()\n if (!state.identities) {\n state.identities = readIdentities()\n }\n return state.identities\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mfe-orchestrator-hub/client",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Framework agnostic client for MFE Orchestrator: resolves version pinned microfrontend URLs from the console manifest",
5
5
  "license": "MIT",
6
6
  "author": "Lorenzo De Francesco",