diff --git a/custom_components/bahmcloud_store/panel/panel.js b/custom_components/bahmcloud_store/panel/panel.js index c2100ab..d24ebb6 100644 --- a/custom_components/bahmcloud_store/panel/panel.js +++ b/custom_components/bahmcloud_store/panel/panel.js @@ -21,9 +21,9 @@ class BahmcloudStorePanel extends HTMLElement { this._detailRepo = null; this._readmeLoading = false; - this._readmeText = null; - this._readmeHtml = null; - this._readmeError = null; + this._readmeText = null; // markdown string + this._readmeHtml = null; // sanitized html string + this._readmeError = null; // string } set hass(hass) { @@ -46,7 +46,7 @@ class BahmcloudStorePanel extends HTMLElement { const data = await this._hass.callApi("get", "bcs"); this._data = data; } catch (e) { - this._error = e?.message ? String(e.message) : String(e); + this._error = this._toErrString(e); } finally { this._loading = false; this._update(); @@ -106,7 +106,7 @@ class BahmcloudStorePanel extends HTMLElement { this._view = "manage"; this._update(); } catch (e) { - this._error = e?.message ? String(e.message) : String(e); + this._error = this._toErrString(e); this._update(); } } @@ -120,7 +120,7 @@ class BahmcloudStorePanel extends HTMLElement { this._view = "manage"; this._update(); } catch (e) { - this._error = e?.message ? String(e.message) : String(e); + this._error = this._toErrString(e); this._update(); } } @@ -142,9 +142,13 @@ class BahmcloudStorePanel extends HTMLElement { this._loadReadme(repoId); } + // --- README fetching (hardened) --- async _loadReadme(repoId) { if (!this._hass) return; + this._readmeLoading = true; + this._readmeText = null; + this._readmeHtml = null; this._readmeError = null; this._update(); @@ -154,18 +158,37 @@ class BahmcloudStorePanel extends HTMLElement { `bcs/readme?repo_id=${encodeURIComponent(repoId)}` ); - if (resp?.ok && typeof resp.readme === "string" && resp.readme.trim()) { - this._readmeText = resp.readme; - this._readmeHtml = typeof resp.html === "string" && resp.html.trim() ? resp.html : null; + // Normalize fields strictly (avoid [object Object]) + const ok = resp && resp.ok === true; + + const readme = (resp && typeof resp.readme === "string") ? resp.readme : null; + const html = (resp && typeof resp.html === "string") ? resp.html : null; + + if (ok && readme && readme.trim()) { + this._readmeText = readme; + this._readmeHtml = html && html.trim() ? html : null; + this._readmeError = null; } else { + // If backend provided a message, convert it safely + const msg = + (resp && typeof resp.message === "string" && resp.message.trim()) + ? resp.message.trim() + : "README not found."; + + // Extra hint if backend returned unexpected types + if (ok && resp && resp.readme && typeof resp.readme !== "string") { + this._readmeError = "README has an unsupported format (expected text)."; + } else { + this._readmeError = msg; + } + this._readmeText = null; this._readmeHtml = null; - this._readmeError = this._safeText(resp?.message) || "README not found."; } } catch (e) { this._readmeText = null; this._readmeHtml = null; - this._readmeError = e?.message ? String(e.message) : String(e); + this._readmeError = this._toErrString(e) || "README not found."; } finally { this._readmeLoading = false; this._update(); @@ -544,10 +567,10 @@ class BahmcloudStorePanel extends HTMLElement { const creator = this._safeText(r?.owner) ? `Creator: ${this._safeText(r?.owner)}` : "Creator: -"; const latest = this._safeText(r?.latest_version) ? `Latest: ${this._safeText(r?.latest_version)}` : "Latest: unknown"; - const cat = this._safeText(r?.category) ? `Category: ${this._safeText(r?.category)}` : null; + const prov = this._safeText(r?.provider) ? `Provider: ${this._safeText(r?.provider)}` : null; const metaSrc = this._safeText(r?.meta_source) ? `Meta: ${this._safeText(r?.meta_source)}` : null; - const lineBits = [creator, latest, cat, metaSrc].filter(Boolean); + const lineBits = [creator, latest, prov, metaSrc].filter(Boolean); return `