@mushi-mushi/web 0.5.0 → 0.5.1

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/dist/index.cjs CHANGED
@@ -893,6 +893,20 @@ var MushiWidget = class {
893
893
  document.body.appendChild(this.host);
894
894
  this.render();
895
895
  }
896
+ updateConfig(config = {}) {
897
+ this.config = {
898
+ ...this.config,
899
+ ...config.position ? { position: config.position } : {},
900
+ ...config.theme ? { theme: config.theme } : {},
901
+ ...config.triggerText !== void 0 ? { triggerText: config.triggerText || "\u{1F41B}" } : {},
902
+ ...config.expandedTitle !== void 0 ? { expandedTitle: config.expandedTitle } : {},
903
+ ...config.mode ? { mode: config.mode } : {},
904
+ ...config.locale ? { locale: config.locale } : {},
905
+ ...config.zIndex !== void 0 ? { zIndex: config.zIndex } : {}
906
+ };
907
+ this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
908
+ this.render();
909
+ }
896
910
  open(options) {
897
911
  if (this.isOpen) return;
898
912
  this.isOpen = true;
@@ -1806,6 +1820,8 @@ var Mushi = class {
1806
1820
  }
1807
1821
  };
1808
1822
  function createInstance(config) {
1823
+ const bootstrapConfig = config;
1824
+ let activeConfig = config;
1809
1825
  const log = config.debug ?? false ? core.createLogger({ scope: "mushi", level: "debug", format: "pretty" }) : core.noopLogger;
1810
1826
  const apiClient = core.createApiClient({
1811
1827
  projectId: config.projectId,
@@ -1816,20 +1832,50 @@ function createInstance(config) {
1816
1832
  const offlineQueue = core.createOfflineQueue(config.offline);
1817
1833
  const rateLimiter = core.createRateLimiter({ maxBurst: 10, refillRate: 1, refillIntervalMs: 5e3 });
1818
1834
  const piiScrubber = core.createPiiScrubber();
1819
- const consoleCap = config.capture?.console !== false ? createConsoleCapture() : null;
1820
- const networkCap = config.capture?.network !== false ? createNetworkCapture() : null;
1821
- const perfCap = config.capture?.performance !== false ? createPerformanceCapture() : null;
1822
- const screenshotCap = config.capture?.screenshot !== "off" ? createScreenshotCapture() : null;
1823
- const elementSelector = config.capture?.elementSelector !== false ? createElementSelector() : null;
1835
+ let consoleCap = null;
1836
+ let networkCap = null;
1837
+ let perfCap = null;
1838
+ let screenshotCap = null;
1839
+ let elementSelector = null;
1840
+ function syncCaptureModules() {
1841
+ if (activeConfig.capture?.console !== false) {
1842
+ consoleCap ??= createConsoleCapture();
1843
+ } else {
1844
+ consoleCap?.destroy();
1845
+ consoleCap = null;
1846
+ }
1847
+ if (activeConfig.capture?.network !== false) {
1848
+ networkCap ??= createNetworkCapture();
1849
+ } else {
1850
+ networkCap?.destroy();
1851
+ networkCap = null;
1852
+ }
1853
+ if (activeConfig.capture?.performance !== false) {
1854
+ perfCap ??= createPerformanceCapture();
1855
+ } else {
1856
+ perfCap?.destroy();
1857
+ perfCap = null;
1858
+ }
1859
+ screenshotCap = activeConfig.capture?.screenshot !== "off" ? screenshotCap ?? createScreenshotCapture() : null;
1860
+ if (!screenshotCap) pendingScreenshot = null;
1861
+ if (activeConfig.capture?.elementSelector !== false) {
1862
+ elementSelector ??= createElementSelector();
1863
+ } else {
1864
+ elementSelector?.deactivate();
1865
+ elementSelector = null;
1866
+ pendingElement = null;
1867
+ }
1868
+ }
1824
1869
  const listeners = /* @__PURE__ */ new Map();
1825
1870
  function emit(type, data) {
1826
1871
  listeners.get(type)?.forEach((handler) => handler({ type, data }));
1827
1872
  }
1828
- let userInfo = null;
1829
- const customMetadata = {};
1830
1873
  let pendingScreenshot = null;
1831
1874
  let pendingElement = null;
1832
1875
  let pendingProactiveTrigger = null;
1876
+ let userInfo = null;
1877
+ const customMetadata = {};
1878
+ syncCaptureModules();
1833
1879
  const widget = new MushiWidget(config.widget, {
1834
1880
  onSubmit: async ({ category, description, intent }) => {
1835
1881
  log.info("Report submitted", { category, intent });
@@ -1852,13 +1898,13 @@ function createInstance(config) {
1852
1898
  emit("widget:closed");
1853
1899
  },
1854
1900
  onScreenshotRequest: async () => {
1855
- if (!screenshotCap) return;
1901
+ if (!screenshotCap || activeConfig.capture?.screenshot === "off") return;
1856
1902
  log.debug("Taking screenshot");
1857
1903
  pendingScreenshot = await screenshotCap.take();
1858
1904
  widget.setScreenshotAttached(pendingScreenshot !== null);
1859
1905
  },
1860
1906
  onElementSelectorRequest: async () => {
1861
- if (!elementSelector) return;
1907
+ if (!elementSelector || activeConfig.capture?.elementSelector === false) return;
1862
1908
  log.debug("Element selector activated");
1863
1909
  const el = await elementSelector.activate();
1864
1910
  if (el) {
@@ -1912,6 +1958,34 @@ function createInstance(config) {
1912
1958
  offlineQueue.flush(apiClient).then((result) => {
1913
1959
  if (result.sent > 0) log.info("Synced offline reports", { sent: result.sent });
1914
1960
  });
1961
+ function applyRuntimeConfig(runtime) {
1962
+ if (runtime.enabled === false) {
1963
+ activeConfig = bootstrapConfig;
1964
+ clearCachedRuntimeConfig(config.projectId);
1965
+ syncCaptureModules();
1966
+ widget.updateConfig(activeConfig.widget);
1967
+ log.debug("Runtime SDK config disabled; using bootstrap config", { version: runtime.version });
1968
+ return;
1969
+ }
1970
+ activeConfig = mergeRuntimeConfig(activeConfig, runtime);
1971
+ syncCaptureModules();
1972
+ if (runtime.widget) widget.updateConfig(activeConfig.widget);
1973
+ log.debug("Applied runtime SDK config", { version: runtime.version });
1974
+ }
1975
+ if (config.runtimeConfig !== false) {
1976
+ const cached = readCachedRuntimeConfig(config.projectId);
1977
+ if (cached) applyRuntimeConfig(cached);
1978
+ apiClient.getSdkConfig().then((result) => {
1979
+ if (result.ok && result.data) {
1980
+ cacheRuntimeConfig(config.projectId, result.data);
1981
+ applyRuntimeConfig(result.data);
1982
+ } else if (result.error) {
1983
+ log.debug("Runtime SDK config unavailable", result.error);
1984
+ }
1985
+ }).catch((err) => {
1986
+ log.debug("Runtime SDK config fetch failed", { error: err instanceof Error ? err.message : String(err) });
1987
+ });
1988
+ }
1915
1989
  log.info("Initialized", { projectId: config.projectId });
1916
1990
  async function submitReport(category, description, intent) {
1917
1991
  const filterResult = preFilter.check(description);
@@ -1961,9 +2035,9 @@ function createInstance(config) {
1961
2035
  description: scrubbedDescription,
1962
2036
  userIntent: intent,
1963
2037
  environment: core.captureEnvironment(),
1964
- consoleLogs: consoleCap?.getEntries(),
1965
- networkLogs: networkCap?.getEntries(),
1966
- performanceMetrics: perfCap?.getMetrics(),
2038
+ consoleLogs: activeConfig.capture?.console === false ? void 0 : consoleCap?.getEntries(),
2039
+ networkLogs: activeConfig.capture?.network === false ? void 0 : networkCap?.getEntries(),
2040
+ performanceMetrics: activeConfig.capture?.performance === false ? void 0 : perfCap?.getMetrics(),
1967
2041
  screenshotDataUrl: pendingScreenshot ?? void 0,
1968
2042
  selectedElement: pendingElement ?? void 0,
1969
2043
  metadata: {
@@ -2038,6 +2112,9 @@ function createInstance(config) {
2038
2112
  close() {
2039
2113
  widget.close();
2040
2114
  },
2115
+ updateConfig(runtimeConfig) {
2116
+ applyRuntimeConfig(runtimeConfig);
2117
+ },
2041
2118
  destroy() {
2042
2119
  proactiveTriggers?.destroy();
2043
2120
  proactiveManager?.reset();
@@ -2106,6 +2183,50 @@ function createInstance(config) {
2106
2183
  };
2107
2184
  return sdk;
2108
2185
  }
2186
+ function mergeRuntimeConfig(config, runtime) {
2187
+ return {
2188
+ ...config,
2189
+ widget: {
2190
+ ...config.widget,
2191
+ ...runtime.widget
2192
+ },
2193
+ capture: {
2194
+ ...config.capture,
2195
+ ...runtime.capture
2196
+ }
2197
+ };
2198
+ }
2199
+ function runtimeConfigCacheKey(projectId) {
2200
+ return `mushi:sdk-config:${projectId}`;
2201
+ }
2202
+ function readCachedRuntimeConfig(projectId) {
2203
+ if (typeof localStorage === "undefined") return null;
2204
+ try {
2205
+ const raw = localStorage.getItem(runtimeConfigCacheKey(projectId));
2206
+ if (!raw) return null;
2207
+ const parsed = JSON.parse(raw);
2208
+ return parsed.config ?? null;
2209
+ } catch {
2210
+ return null;
2211
+ }
2212
+ }
2213
+ function cacheRuntimeConfig(projectId, config) {
2214
+ if (typeof localStorage === "undefined") return;
2215
+ try {
2216
+ localStorage.setItem(runtimeConfigCacheKey(projectId), JSON.stringify({
2217
+ cachedAt: Date.now(),
2218
+ config
2219
+ }));
2220
+ } catch {
2221
+ }
2222
+ }
2223
+ function clearCachedRuntimeConfig(projectId) {
2224
+ if (typeof localStorage === "undefined") return;
2225
+ try {
2226
+ localStorage.removeItem(runtimeConfigCacheKey(projectId));
2227
+ } catch {
2228
+ }
2229
+ }
2109
2230
  function createNoopInstance() {
2110
2231
  return {
2111
2232
  report: () => {
@@ -2121,6 +2242,8 @@ function createNoopInstance() {
2121
2242
  },
2122
2243
  close: () => {
2123
2244
  },
2245
+ updateConfig: () => {
2246
+ },
2124
2247
  destroy: () => {
2125
2248
  instance = null;
2126
2249
  },