@trops/dash-core 0.1.244 → 0.1.247

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.
@@ -632,29 +632,39 @@ var clientCacheEvents$1 = {
632
632
  * IPC event constants for dashboard configuration export/import.
633
633
  */
634
634
 
635
- const DASHBOARD_CONFIG_EXPORT$1 = "dashboard-config-export";
636
- const DASHBOARD_CONFIG_IMPORT$1 = "dashboard-config-import";
637
- const DASHBOARD_CONFIG_INSTALL$1 = "dashboard-config-install";
638
- const DASHBOARD_CONFIG_COMPATIBILITY$1 = "dashboard-config-compatibility";
639
- const DASHBOARD_CONFIG_PUBLISH$1 = "dashboard-config-publish";
640
- const DASHBOARD_CONFIG_PREVIEW$1 = "dashboard-config-preview";
641
- const DASHBOARD_CONFIG_CHECK_UPDATES$1 = "dashboard-config-check-updates";
642
- const DASHBOARD_CONFIG_PROVIDER_SETUP$1 = "dashboard-config-provider-setup";
643
- const DASHBOARD_CONFIG_PUBLISH_PREVIEW$1 = "dashboard-config-publish-preview";
644
- const DASHBOARD_CONFIG_SELECT_FILE$1 = "dashboard-config-select-file";
645
-
646
- var dashboardConfigEvents$1 = {
647
- DASHBOARD_CONFIG_EXPORT: DASHBOARD_CONFIG_EXPORT$1,
648
- DASHBOARD_CONFIG_IMPORT: DASHBOARD_CONFIG_IMPORT$1,
649
- DASHBOARD_CONFIG_INSTALL: DASHBOARD_CONFIG_INSTALL$1,
650
- DASHBOARD_CONFIG_COMPATIBILITY: DASHBOARD_CONFIG_COMPATIBILITY$1,
651
- DASHBOARD_CONFIG_PUBLISH: DASHBOARD_CONFIG_PUBLISH$1,
652
- DASHBOARD_CONFIG_PREVIEW: DASHBOARD_CONFIG_PREVIEW$1,
653
- DASHBOARD_CONFIG_CHECK_UPDATES: DASHBOARD_CONFIG_CHECK_UPDATES$1,
654
- DASHBOARD_CONFIG_PROVIDER_SETUP: DASHBOARD_CONFIG_PROVIDER_SETUP$1,
655
- DASHBOARD_CONFIG_PUBLISH_PREVIEW: DASHBOARD_CONFIG_PUBLISH_PREVIEW$1,
656
- DASHBOARD_CONFIG_SELECT_FILE: DASHBOARD_CONFIG_SELECT_FILE$1,
657
- };
635
+ var dashboardConfigEvents$1;
636
+ var hasRequiredDashboardConfigEvents;
637
+
638
+ function requireDashboardConfigEvents () {
639
+ if (hasRequiredDashboardConfigEvents) return dashboardConfigEvents$1;
640
+ hasRequiredDashboardConfigEvents = 1;
641
+ const DASHBOARD_CONFIG_EXPORT = "dashboard-config-export";
642
+ const DASHBOARD_CONFIG_IMPORT = "dashboard-config-import";
643
+ const DASHBOARD_CONFIG_INSTALL = "dashboard-config-install";
644
+ const DASHBOARD_CONFIG_COMPATIBILITY = "dashboard-config-compatibility";
645
+ const DASHBOARD_CONFIG_PUBLISH = "dashboard-config-publish";
646
+ const DASHBOARD_CONFIG_PREVIEW = "dashboard-config-preview";
647
+ const DASHBOARD_CONFIG_CHECK_UPDATES = "dashboard-config-check-updates";
648
+ const DASHBOARD_CONFIG_PROVIDER_SETUP = "dashboard-config-provider-setup";
649
+ const DASHBOARD_CONFIG_PUBLISH_PREVIEW = "dashboard-config-publish-preview";
650
+ const DASHBOARD_CONFIG_SELECT_FILE = "dashboard-config-select-file";
651
+ const DASHBOARD_CONFIG_INSTALL_PROGRESS = "dashboard-config-install-progress";
652
+
653
+ dashboardConfigEvents$1 = {
654
+ DASHBOARD_CONFIG_EXPORT,
655
+ DASHBOARD_CONFIG_IMPORT,
656
+ DASHBOARD_CONFIG_INSTALL,
657
+ DASHBOARD_CONFIG_COMPATIBILITY,
658
+ DASHBOARD_CONFIG_PUBLISH,
659
+ DASHBOARD_CONFIG_PREVIEW,
660
+ DASHBOARD_CONFIG_CHECK_UPDATES,
661
+ DASHBOARD_CONFIG_PROVIDER_SETUP,
662
+ DASHBOARD_CONFIG_PUBLISH_PREVIEW,
663
+ DASHBOARD_CONFIG_SELECT_FILE,
664
+ DASHBOARD_CONFIG_INSTALL_PROGRESS,
665
+ };
666
+ return dashboardConfigEvents$1;
667
+ }
658
668
 
659
669
  /**
660
670
  * Dashboard Ratings Events
@@ -924,7 +934,7 @@ const menuItemEvents = menuItemEvents$1;
924
934
  const openaiEvents = openaiEvents$1;
925
935
  const llmEvents = llmEvents$1;
926
936
  const clientCacheEvents = clientCacheEvents$1;
927
- const dashboardConfigEvents = dashboardConfigEvents$1;
937
+ const dashboardConfigEvents = requireDashboardConfigEvents();
928
938
  const dashboardRatingsEvents = dashboardRatingsEvents$1;
929
939
  const registryAuthEvents = registryAuthEvents$1;
930
940
  const sessionEvents = sessionEvents$1;
@@ -29222,6 +29232,16 @@ function buildWidgetDependencies$1(
29222
29232
  }
29223
29233
  }
29224
29234
 
29235
+ // Final fallback: if widget name looks like a scoped id, parse it
29236
+ if (!packageName || packageName === name) {
29237
+ const idParts = name.split(".");
29238
+ if (idParts.length === 3) {
29239
+ scope = scope || idParts[0];
29240
+ packageName = idParts[1];
29241
+ widgetName = idParts[2];
29242
+ }
29243
+ }
29244
+
29225
29245
  const id =
29226
29246
  scope && packageName && widgetName
29227
29247
  ? `${scope}.${packageName}.${widgetName}`
@@ -31442,8 +31462,49 @@ var schedulerController_1 = schedulerController$2;
31442
31462
  if (!response.ok)
31443
31463
  throw new Error(`Failed to fetch: ${response.statusText}`);
31444
31464
 
31445
- const buffer = await response.arrayBuffer();
31446
- const zip = new AdmZip(Buffer.from(buffer));
31465
+ const contentType = response.headers.get("content-type") || "";
31466
+ let buffer = Buffer.from(await response.arrayBuffer());
31467
+
31468
+ if (buffer.length === 0) {
31469
+ throw new Error("Download failed: registry returned an empty response");
31470
+ }
31471
+
31472
+ if (contentType.includes("text/html")) {
31473
+ throw new Error(
31474
+ "Download failed: registry returned an HTML page instead of package data",
31475
+ );
31476
+ }
31477
+
31478
+ // Registry download endpoints return JSON with a pre-signed S3 URL
31479
+ if (contentType.includes("application/json")) {
31480
+ let jsonData;
31481
+ try {
31482
+ jsonData = JSON.parse(buffer.toString("utf-8"));
31483
+ } catch (parseErr) {
31484
+ throw new Error(
31485
+ `Download failed: invalid JSON (${parseErr.message})`,
31486
+ );
31487
+ }
31488
+ if (jsonData.error) {
31489
+ throw new Error(`Download failed: ${jsonData.error}`);
31490
+ }
31491
+ if (jsonData.downloadUrl) {
31492
+ const zipResponse = await fetch(jsonData.downloadUrl);
31493
+ if (!zipResponse.ok) {
31494
+ throw new Error(
31495
+ `Download failed: storage returned ${zipResponse.status} ${zipResponse.statusText}`,
31496
+ );
31497
+ }
31498
+ buffer = Buffer.from(await zipResponse.arrayBuffer());
31499
+ if (buffer.length === 0) {
31500
+ throw new Error(
31501
+ "Download failed: storage returned an empty ZIP file",
31502
+ );
31503
+ }
31504
+ }
31505
+ }
31506
+
31507
+ const zip = new AdmZip(buffer);
31447
31508
 
31448
31509
  // Scoped names (e.g. "@trops/slack") get nested dirs: widgets/@trops/slack/
31449
31510
  const widgetPath = path.join(WIDGETS_CACHE_DIR, ...widgetName.split("/"));
@@ -33090,6 +33151,10 @@ async function processDashboardConfig(
33090
33151
  failed: [],
33091
33152
  };
33092
33153
 
33154
+ const {
33155
+ DASHBOARD_CONFIG_INSTALL_PROGRESS,
33156
+ } = requireDashboardConfigEvents();
33157
+
33093
33158
  if (
33094
33159
  widgetRegistry &&
33095
33160
  dashboardConfig.widgets &&
@@ -33097,39 +33162,112 @@ async function processDashboardConfig(
33097
33162
  ) {
33098
33163
  const installedWidgets = widgetRegistry.getWidgets();
33099
33164
  const installedPackages = new Set(installedWidgets.map((w) => w.name));
33165
+ const total = dashboardConfig.widgets.length;
33166
+
33167
+ // Emit initial "pending" state for all widgets
33168
+ for (let i = 0; i < total; i++) {
33169
+ const dep = dashboardConfig.widgets[i];
33170
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33171
+ packageName: dep.package,
33172
+ displayName: dep.displayName || dep.name || dep.package,
33173
+ status: "pending",
33174
+ index: i,
33175
+ total,
33176
+ });
33177
+ }
33100
33178
 
33101
- for (const widgetDep of dashboardConfig.widgets) {
33179
+ for (let i = 0; i < total; i++) {
33180
+ const widgetDep = dashboardConfig.widgets[i];
33102
33181
  const packageName = widgetDep.package;
33182
+ const displayName =
33183
+ widgetDep.displayName || widgetDep.name || packageName;
33103
33184
 
33104
33185
  if (installedPackages.has(packageName)) {
33105
33186
  installSummary.alreadyInstalled.push(packageName);
33187
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33188
+ packageName,
33189
+ displayName,
33190
+ status: "already-installed",
33191
+ index: i,
33192
+ total,
33193
+ });
33106
33194
  continue;
33107
33195
  }
33108
33196
 
33197
+ // Emit downloading status
33198
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33199
+ packageName,
33200
+ displayName,
33201
+ status: "downloading",
33202
+ index: i,
33203
+ total,
33204
+ });
33205
+
33109
33206
  // Try to find the widget in the registry and install it
33110
33207
  try {
33111
33208
  const registryPkg = await getPackage(packageName);
33112
33209
  if (registryPkg && registryPkg.downloadUrl) {
33113
- await widgetRegistry.downloadWidget(
33210
+ const config = await widgetRegistry.downloadWidget(
33114
33211
  packageName,
33115
33212
  registryPkg.downloadUrl,
33116
33213
  registryPkg.dashConfigUrl || null,
33117
33214
  );
33118
- installSummary.installed.push(packageName);
33215
+ installSummary.installed.push({ packageName, config });
33119
33216
  installedPackages.add(packageName);
33217
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33218
+ packageName,
33219
+ displayName,
33220
+ status: "installed",
33221
+ index: i,
33222
+ total,
33223
+ });
33120
33224
  } else {
33121
33225
  installSummary.failed.push({
33122
33226
  package: packageName,
33123
33227
  reason: "Not found in registry",
33124
33228
  });
33229
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33230
+ packageName,
33231
+ displayName,
33232
+ status: "failed",
33233
+ index: i,
33234
+ total,
33235
+ error: "Not found in registry",
33236
+ });
33125
33237
  }
33126
33238
  } catch (installError) {
33127
33239
  installSummary.failed.push({
33128
33240
  package: packageName,
33129
33241
  reason: installError.message,
33130
33242
  });
33243
+ win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
33244
+ packageName,
33245
+ displayName,
33246
+ status: "failed",
33247
+ index: i,
33248
+ total,
33249
+ error: installError.message,
33250
+ });
33251
+ }
33252
+ }
33253
+
33254
+ // Notify renderer about auto-installed widgets
33255
+ if (installSummary.installed.length > 0) {
33256
+ const { BrowserWindow } = require$$0$2;
33257
+ for (const { packageName, config } of installSummary.installed) {
33258
+ BrowserWindow.getAllWindows().forEach((w) => {
33259
+ w.webContents.send("widget:installed", {
33260
+ widgetName: packageName,
33261
+ config: config || {},
33262
+ });
33263
+ });
33131
33264
  }
33132
33265
  }
33266
+
33267
+ // Flatten installed list to just package names for the summary
33268
+ installSummary.installed = installSummary.installed.map((entry) =>
33269
+ typeof entry === "string" ? entry : entry.packageName,
33270
+ );
33133
33271
  }
33134
33272
 
33135
33273
  // 2. Install bundled theme if present
@@ -68924,6 +69062,7 @@ const {
68924
69062
  DASHBOARD_CONFIG_CHECK_UPDATES,
68925
69063
  DASHBOARD_CONFIG_PROVIDER_SETUP,
68926
69064
  DASHBOARD_CONFIG_PUBLISH_PREVIEW,
69065
+ DASHBOARD_CONFIG_INSTALL_PROGRESS,
68927
69066
  } = events$8;
68928
69067
 
68929
69068
  const dashboardConfigApi$2 = {
@@ -69053,6 +69192,20 @@ const dashboardConfigApi$2 = {
69053
69192
  appId,
69054
69193
  workspaceId,
69055
69194
  }),
69195
+
69196
+ /**
69197
+ * Listen for dashboard install progress events.
69198
+ * Emitted per-widget during dashboard installation.
69199
+ *
69200
+ * @param {Function} callback - (data: {packageName, displayName, status, index, total, error?})
69201
+ * @returns {Function} removeListener cleanup function
69202
+ */
69203
+ onInstallProgress: (callback) => {
69204
+ const handler = (_event, data) => callback(data);
69205
+ ipcRenderer$9.on(DASHBOARD_CONFIG_INSTALL_PROGRESS, handler);
69206
+ return () =>
69207
+ ipcRenderer$9.removeListener(DASHBOARD_CONFIG_INSTALL_PROGRESS, handler);
69208
+ },
69056
69209
  };
69057
69210
 
69058
69211
  var dashboardConfigApi_1 = dashboardConfigApi$2;