@trops/dash-core 0.1.286 → 0.1.288

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.
@@ -31578,6 +31578,77 @@ var schedulerController_1 = schedulerController$2;
31578
31578
  } catch (error) {
31579
31579
  console.error("[WidgetRegistry] Error loading registry:", error);
31580
31580
  }
31581
+
31582
+ // Reconcile: re-register orphaned widget packages found on disk
31583
+ this.reconcileWithDisk();
31584
+ }
31585
+
31586
+ /**
31587
+ * Scan the widgets directory for packages that exist on disk but are
31588
+ * missing from the registry (e.g. because registry.json was manually edited).
31589
+ * Re-registers them so they can be properly managed (listed, uninstalled).
31590
+ */
31591
+ reconcileWithDisk() {
31592
+ try {
31593
+ if (!WIDGETS_CACHE_DIR || !fs.existsSync(WIDGETS_CACHE_DIR)) return;
31594
+
31595
+ const registeredPaths = new Set(
31596
+ Array.from(this.widgets.values()).map((w) => w.path),
31597
+ );
31598
+ let reconciled = false;
31599
+
31600
+ const entries = fs.readdirSync(WIDGETS_CACHE_DIR, {
31601
+ withFileTypes: true,
31602
+ });
31603
+ for (const entry of entries) {
31604
+ if (!entry.isDirectory()) continue;
31605
+
31606
+ if (entry.name.startsWith("@")) {
31607
+ // Scoped packages: @scope/name
31608
+ const scopeDir = path.join(WIDGETS_CACHE_DIR, entry.name);
31609
+ const pkgs = fs.readdirSync(scopeDir, { withFileTypes: true });
31610
+ for (const pkg of pkgs) {
31611
+ if (!pkg.isDirectory()) continue;
31612
+ const pkgPath = path.join(scopeDir, pkg.name);
31613
+ const pkgId = `${entry.name}/${pkg.name}`;
31614
+ if (!registeredPaths.has(pkgPath) && !this.widgets.has(pkgId)) {
31615
+ this._reregisterOrphan(pkgId, pkgPath);
31616
+ reconciled = true;
31617
+ }
31618
+ }
31619
+ } else if (entry.name !== "registry.json") {
31620
+ // Bare-name packages
31621
+ const pkgPath = path.join(WIDGETS_CACHE_DIR, entry.name);
31622
+ if (!registeredPaths.has(pkgPath) && !this.widgets.has(entry.name)) {
31623
+ this._reregisterOrphan(entry.name, pkgPath);
31624
+ reconciled = true;
31625
+ }
31626
+ }
31627
+ }
31628
+
31629
+ if (reconciled) {
31630
+ this.saveRegistry();
31631
+ console.log("[WidgetRegistry] Disk reconciliation complete");
31632
+ }
31633
+ } catch (err) {
31634
+ console.warn("[WidgetRegistry] Reconciliation error:", err.message);
31635
+ }
31636
+ }
31637
+
31638
+ /**
31639
+ * Re-register an orphaned widget package found on disk.
31640
+ */
31641
+ _reregisterOrphan(pkgId, pkgPath) {
31642
+ console.log(`[WidgetRegistry] Re-registering orphaned widget: ${pkgId}`);
31643
+ const { scope } = parsePackageId(pkgId);
31644
+ this.widgets.set(pkgId, {
31645
+ name: pkgId,
31646
+ packageId: pkgId,
31647
+ scope: scope || null,
31648
+ path: pkgPath,
31649
+ version: null,
31650
+ orphaned: true,
31651
+ });
31581
31652
  }
31582
31653
 
31583
31654
  /**
@@ -32171,10 +32242,23 @@ var schedulerController_1 = schedulerController$2;
32171
32242
  * @param {string} widgetName - Name of the widget to remove
32172
32243
  */
32173
32244
  uninstallWidget(widgetName) {
32174
- const widget = this.widgets.get(widgetName);
32245
+ let widget = this.widgets.get(widgetName);
32246
+
32247
+ // Fallback: widget not in registry but might exist on disk
32175
32248
  if (!widget) {
32176
- console.warn(`[WidgetRegistry] Widget not found: ${widgetName}`);
32177
- return false;
32249
+ const candidatePath = path.join(
32250
+ WIDGETS_CACHE_DIR,
32251
+ ...widgetName.split("/"),
32252
+ );
32253
+ if (fs.existsSync(candidatePath)) {
32254
+ widget = { path: candidatePath };
32255
+ console.log(
32256
+ `[WidgetRegistry] Widget ${widgetName} not in registry, removing from disk`,
32257
+ );
32258
+ } else {
32259
+ console.warn(`[WidgetRegistry] Widget not found: ${widgetName}`);
32260
+ return false;
32261
+ }
32178
32262
  }
32179
32263
 
32180
32264
  try {
@@ -32347,7 +32431,13 @@ var schedulerController_1 = schedulerController$2;
32347
32431
  ipcMain.handle("widget:uninstall", (event, widgetName) => {
32348
32432
  const schedulerController = schedulerController_1;
32349
32433
  schedulerController.cleanupWidget(widgetName);
32350
- return getWidgetRegistry().uninstallWidget(widgetName);
32434
+ const success = getWidgetRegistry().uninstallWidget(widgetName);
32435
+ if (success) {
32436
+ BrowserWindow.getAllWindows().forEach((win) => {
32437
+ win.webContents.send("widget:uninstalled", { widgetName });
32438
+ });
32439
+ }
32440
+ return success;
32351
32441
  });
32352
32442
 
32353
32443
  ipcMain.handle("widget:cache-path", () => getWidgetRegistry().getCachePath());
@@ -68929,6 +69019,23 @@ const widgetApi$2 = {
68929
69019
  });
68930
69020
  },
68931
69021
 
69022
+ /**
69023
+ * Listen for widget uninstallation events
69024
+ * Useful for cleaning up ComponentManager entries and refreshing UI
69025
+ *
69026
+ * @param {Function} callback - Function called when a widget is uninstalled
69027
+ *
69028
+ * @example
69029
+ * mainApi.widgets.onUninstalled(({ widgetName }) => {
69030
+ * console.log(`Widget ${widgetName} was uninstalled!`);
69031
+ * });
69032
+ */
69033
+ onUninstalled: (callback) => {
69034
+ ipcRenderer$k.on("widget:uninstalled", (event, data) => {
69035
+ callback(data);
69036
+ });
69037
+ },
69038
+
68932
69039
  /**
68933
69040
  * Listen for batch widget loading events
68934
69041
  * Useful for updating UI when multiple widgets are loaded at once
@@ -68956,6 +69063,15 @@ const widgetApi$2 = {
68956
69063
  ipcRenderer$k.removeListener("widget:installed", callback);
68957
69064
  },
68958
69065
 
69066
+ /**
69067
+ * Remove listener for widget uninstallation events
69068
+ *
69069
+ * @param {Function} callback - The callback to remove
69070
+ */
69071
+ removeUninstalledListener: (callback) => {
69072
+ ipcRenderer$k.removeListener("widget:uninstalled", callback);
69073
+ },
69074
+
68959
69075
  /**
68960
69076
  * Remove listener for batch widget loading events
68961
69077
  *