blazor-micro-frontends
Version:
Streamlined creation and integration of micro frontends using ASP.NET Blazor (Server/WebAssembly).
294 lines (293 loc) • 9.59 kB
JavaScript
class u {
get retryMaximumCount() {
return this.retryMaximun;
}
get retryIntervallInMilliseconds() {
return this.retryIntervall;
}
constructor(e, t) {
this.retryMaximun = e, this.retryIntervall = t, this.isReconnectCanceled = !1;
}
async onConnectionDownAsync() {
this.showReconnectModel(), await this.tryReconnectAsync();
}
onConnectionUp() {
this.isReconnectCanceled = !0, this.hideReconnectModel();
}
showReconnectModel() {
this.updateReconnectModal((e) => {
const t = e.classList;
t.contains("components-reconnect-modal-visible") || (this.resetReconnectModal(e), t.add("components-reconnect-modal-visible"));
});
}
hideReconnectModel() {
this.updateReconnectModal((e) => {
const t = e.classList;
t.contains("components-reconnect-modal-visible") && (t.remove("components-reconnect-modal-visible"), this.resetReconnectModal(e));
});
}
updateReconnectModal(e) {
this.reconnectionModals = document.querySelectorAll(".components-reconnect-modal"), this.reconnectionModals.forEach((t) => {
e(t);
});
}
async tryReconnectAsync() {
this.isReconnectCanceled = !1;
for (let e = 0; e < this.retryMaximun; e++) {
if (this.isReconnectCanceled)
return;
this.updateReconnectText(e);
try {
if (await window.Blazor.reconnect())
return;
this.showReloadButton();
return;
} catch {
}
await new Promise((t) => setTimeout(t, this.retryIntervall));
}
this.showReloadButton();
}
showReloadButton() {
this.updateReconnectModal((e) => {
this.hideReconnectSpinner(e), this.hideReconnectText(e);
const t = e.querySelector(".components-reconnect-button");
if (!t)
return;
const n = t.classList;
n.contains("components-reconnect-button-visible") || n.add("components-reconnect-button-visible");
});
}
updateReconnectText(e) {
const t = this.retryMaximun - e;
this.updateReconnectModal((n) => {
const o = n.querySelector(".components-reconnect-count");
o && (o.innerHTML = t.toString());
});
}
hideReconnectSpinner(e) {
const t = e.querySelector(".components-reconnect-spinner");
if (!t)
return;
const n = t.classList;
n.contains("components-reconnect-spinner-hidden") || n.add("components-reconnect-spinner-hidden");
}
hideReconnectText(e) {
const t = e.querySelector(".components-reconnect-count");
if (!t)
return;
const n = t.classList;
n.contains("components-reconnect-count-hidden") || n.add("components-reconnect-count-hidden");
}
resetReconnectModal(e) {
const t = e.querySelector(".components-reconnect-spinner"), n = e.querySelector(".components-reconnect-count");
if (!n || !t)
return;
t.classList.remove("components-reconnect-spinner-hidden"), n.classList.remove("components-reconnect-count-hidden"), n.innerHTML = "";
}
}
async function a(s, e, t = !0) {
return new Promise((n, o) => {
const r = document.createElement("script"), c = () => {
t && document.body.removeChild(r);
};
r.crossOrigin = "anonymous", r.async = !0, r.src = s, r.onload = () => {
c(), n();
}, r.onerror = () => {
c(), o(new Error("Failed to load script."));
}, e == null || e(r), document.body.appendChild(r);
});
}
async function h(s, e) {
if (!e)
return;
const t = `${s}${e}.modules.json`, n = await fetch(t, { headers: { "Content-Type": "application/json" } });
if (!n.ok)
return;
const o = await n.json();
await Promise.all(o.map(async (r) => {
await a(`${s}${r}`, (c) => {
c.type = "module";
});
}));
}
class d {
constructor(e) {
this.pathBase = e;
}
async startAsync(e) {
if (!this.blazorScript) {
console.error("No blazor script available.");
return;
}
await a(this.blazorScript, (n) => {
n.setAttribute("autostart", "false");
});
const t = e ?? this.getDefaultOptions();
window.Blazor.start(t);
}
}
class w extends d {
constructor(e, t) {
super(e), this.transport = t ? 4 : 5, this.blazorScript = `${this.pathBase}_framework/blazor.server.js`;
}
useModulesLoader(e) {
return this.moduleName = e, this;
}
setReconnectSettings(e, t) {
return this.retryMaximun = e, this.retryIntervall = t, this;
}
getDefaultOptions() {
const e = new u(this.retryMaximun ?? 10, this.retryIntervall ?? 1e3);
return {
initializers: { beforeStart: [() => h(this.pathBase, this.moduleName)] },
configureSignalR: (t) => t.withUrl(`${this.pathBase}_blazor`, this.transport),
reconnectionOptions: {
maxRetries: e.retryMaximumCount,
retryIntervalMilliseconds: e.retryIntervallInMilliseconds
},
reconnectionHandler: {
onConnectionDown: () => e.onConnectionDownAsync(),
onConnectionUp: () => e.onConnectionUp()
}
};
}
}
function p(s, e, t, n, o) {
if (e === "manifest")
return S(n, s);
const r = new URL(s, document.baseURI), i = new URL(n, r).toString();
return !o || location.hostname === "localhost" || e === "dotnetjs" || e === "configuration" ? i : z(e, i, o);
}
async function S(s, e) {
var i;
const t = await fetch(s, { cache: "no-cache" });
if (!t.ok || e.length < 2)
return t;
const n = await t.json(), o = new URL(document.baseURI), r = e.replace(o.pathname, "");
if ((i = n.resources) != null && i.libraryInitializers) {
const y = n.resources.libraryInitializers, l = {};
for (const [m, f] of Object.entries(y)) {
const b = `${r}${m}`;
l[b] = f;
}
n.resources.libraryInitializers = l;
}
const c = "application/json";
return new Response(JSON.stringify(n), { headers: { "content-type": c } });
}
async function z(s, e, t) {
const n = await fetch(`${e}${t.extension}`, { cache: "no-cache" });
if (!n.ok)
return fetch(e);
const o = await n.arrayBuffer(), r = new Int8Array(o), c = t.decode(r), i = s === "dotnetwasm" ? "application/wasm" : "application/octet-stream";
return new Response(c, { headers: { "content-type": i } });
}
class C extends d {
constructor(e) {
super(e), this.blazorScript = `${this.pathBase}_framework/blazor.webassembly.js`;
}
useDecoder(e, t) {
return this.decoder = {
decode: e,
extension: t
}, this;
}
getDefaultOptions() {
return {
loadBootResource: (e, t, n) => p(this.pathBase, e, t, n, this.decoder)
};
}
}
class v extends w {
constructor(e, t) {
super(e, t), this.blazorScript = `${this.pathBase}_framework/blazor.web.js`;
}
useDecoder(e, t) {
return this.decoder = {
decode: e,
extension: t
}, this;
}
getDefaultOptions() {
const e = new u(this.retryMaximun ?? 10, this.retryIntervall ?? 1e3);
return {
circuit: {
initializers: { beforeStart: [() => h(this.pathBase, this.moduleName)] },
configureSignalR: (t) => t.withUrl(`${this.pathBase}_blazor`, this.transport),
reconnectionOptions: {
maxRetries: e.retryMaximumCount,
retryIntervalMilliseconds: e.retryIntervallInMilliseconds
},
reconnectionHandler: {
onConnectionDown: () => e.onConnectionDownAsync(),
onConnectionUp: () => e.onConnectionUp()
}
},
webAssembly: {
loadBootResource: (t, n, o) => p(this.pathBase, t, n, o, this.decoder)
}
};
}
}
async function R(s, e) {
return new Promise((t, n) => {
const o = document.createElement("link");
o.crossOrigin = "anonymous", o.rel = "stylesheet", o.href = s, o.onload = () => t(), o.onerror = () => {
const r = "Failed to load style.";
n(new Error(r));
}, document.head.appendChild(o);
});
}
class g {
constructor(e, t) {
this.longPolling = !1, this.basePath = e, this.crossOrigin = t ?? "anonymous", this.blazorScripts = /* @__PURE__ */ new Map(), this.blazorStyles = /* @__PURE__ */ new Map();
}
useScripts(...e) {
return e.forEach((t) => {
const n = `${this.basePath}${t}`, o = `body script[src="${n}"]`;
this.blazorScripts.set(n, o);
}), this;
}
useStyles(...e) {
return e.forEach((t) => {
const n = `${this.basePath}${t}`, o = `head link[href="${n}"]`;
this.blazorStyles.set(n, o);
}), this;
}
useLongPolling() {
return this.longPolling = !0, this;
}
async initializeAsync() {
if (this.blazorScripts.size < 1) {
console.warn("No scripts are added.");
return;
}
const e = this.blazorScripts.keys().next();
if (!(await fetch(e.value)).ok)
return console.warn("The service is currently unavailable."), Promise.resolve(void 0);
for (const [n, o] of this.blazorStyles)
await this.addStylesAsync(n, o);
for (const [n, o] of this.blazorScripts)
await this.addScriptAsync(n, o);
}
addScriptAsync(e, t) {
return document.querySelector(t) ? Promise.resolve() : a(e, (o) => {
o.crossOrigin = this.crossOrigin, o.setAttribute("data-base-path", this.getScriptBasePath()), this.longPolling && o.setAttribute("data-long-polling", "true");
}, !1);
}
getScriptBasePath() {
const e = new URL(document.baseURI).pathname;
let t = this.basePath;
return t.startsWith(e) && (t = t.slice(e.length)), t.startsWith("/") ? t : `/${t}`;
}
addStylesAsync(e, t) {
return document.querySelector(t) ? Promise.resolve() : R(e);
}
}
export {
g as BlazorInitializerClient,
w as BlazorInitializerServer,
C as BlazorInitializerWasm,
v as BlazorInitializerWeb
};