@trops/dash-core 0.1.88 → 0.1.89

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.
@@ -590,12 +590,14 @@ const DASHBOARD_CONFIG_EXPORT$1 = "dashboard-config-export";
590
590
  const DASHBOARD_CONFIG_IMPORT$1 = "dashboard-config-import";
591
591
  const DASHBOARD_CONFIG_INSTALL$1 = "dashboard-config-install";
592
592
  const DASHBOARD_CONFIG_COMPATIBILITY$1 = "dashboard-config-compatibility";
593
+ const DASHBOARD_CONFIG_PUBLISH$1 = "dashboard-config-publish";
593
594
 
594
595
  var dashboardConfigEvents$1 = {
595
596
  DASHBOARD_CONFIG_EXPORT: DASHBOARD_CONFIG_EXPORT$1,
596
597
  DASHBOARD_CONFIG_IMPORT: DASHBOARD_CONFIG_IMPORT$1,
597
598
  DASHBOARD_CONFIG_INSTALL: DASHBOARD_CONFIG_INSTALL$1,
598
599
  DASHBOARD_CONFIG_COMPATIBILITY: DASHBOARD_CONFIG_COMPATIBILITY$1,
600
+ DASHBOARD_CONFIG_PUBLISH: DASHBOARD_CONFIG_PUBLISH$1,
599
601
  };
600
602
 
601
603
  /**
@@ -8443,6 +8445,58 @@ function checkDashboardCompatibility(
8443
8445
  };
8444
8446
  }
8445
8447
 
8448
+ /**
8449
+ * Generate a registry manifest from a dashboard config.
8450
+ * Converts the internal .dashboard.json format into the registry
8451
+ * manifest.json format used by dash-registry.
8452
+ *
8453
+ * @param {Object} dashboardConfig - Validated dashboard config object
8454
+ * @param {Object} options - Publishing options
8455
+ * @param {string} options.githubUser - GitHub username / org for the package scope
8456
+ * @param {string} options.category - Registry category (default: "general")
8457
+ * @param {string} options.repository - Repository URL (optional)
8458
+ * @returns {Object} Registry manifest object
8459
+ */
8460
+ function generateRegistryManifest(dashboardConfig, options = {}) {
8461
+ const name = (dashboardConfig.name || "dashboard")
8462
+ .replace(/[^a-zA-Z0-9-_ ]/g, "")
8463
+ .replace(/\s+/g, "-")
8464
+ .toLowerCase();
8465
+
8466
+ const githubUser = options.githubUser || "";
8467
+ const version = dashboardConfig.workspace?.version
8468
+ ? `1.0.${dashboardConfig.workspace.version}`
8469
+ : "1.0.0";
8470
+
8471
+ const manifest = {
8472
+ githubUser,
8473
+ name,
8474
+ displayName: dashboardConfig.name || "Dashboard",
8475
+ author: dashboardConfig.author?.name || "",
8476
+ description: dashboardConfig.description || "",
8477
+ version,
8478
+ type: "dashboard",
8479
+ category: options.category || "general",
8480
+ tags: dashboardConfig.tags || [],
8481
+ icon: dashboardConfig.icon || "grip",
8482
+ downloadUrl: `https://github.com/${githubUser}/dash-registry/releases/download/${githubUser}--${name}--v{version}/${name}-v{version}.zip`,
8483
+ repository: options.repository || "",
8484
+ publishedAt: new Date().toISOString(),
8485
+ widgets: (dashboardConfig.widgets || []).map((w) => ({
8486
+ id: w.id,
8487
+ name: w.id ? w.id.split(".").pop() : w.package,
8488
+ package: w.package,
8489
+ version: w.version || "*",
8490
+ required: w.required !== false,
8491
+ author: w.author || "",
8492
+ })),
8493
+ providers: dashboardConfig.providers || [],
8494
+ eventWiring: dashboardConfig.eventWiring || [],
8495
+ };
8496
+
8497
+ return manifest;
8498
+ }
8499
+
8446
8500
  var dashboardConfigUtils$1 = {
8447
8501
  collectComponentNames: collectComponentNames$1,
8448
8502
  extractEventWiring: extractEventWiring$1,
@@ -8450,6 +8504,7 @@ var dashboardConfigUtils$1 = {
8450
8504
  buildProviderRequirements: buildProviderRequirements$1,
8451
8505
  applyEventWiringToLayout: applyEventWiringToLayout$1,
8452
8506
  checkDashboardCompatibility,
8507
+ generateRegistryManifest,
8453
8508
  };
8454
8509
 
8455
8510
  var widgetRegistry$1 = {exports: {}};
@@ -10391,11 +10446,191 @@ async function checkCompatibility$1(dashboardWidgets, widgetRegistry = null) {
10391
10446
  );
10392
10447
  }
10393
10448
 
10449
+ /**
10450
+ * Prepare a dashboard for publishing to the registry.
10451
+ *
10452
+ * Validates that the workspace is shareable, builds the dashboard config,
10453
+ * checks that all widgets exist in the registry, generates a registry
10454
+ * manifest, and creates a ZIP containing both the manifest and
10455
+ * .dashboard.json config.
10456
+ *
10457
+ * @param {BrowserWindow} win - The main window (for save dialog)
10458
+ * @param {string} appId - Application identifier
10459
+ * @param {number|string} workspaceId - ID of the workspace to publish
10460
+ * @param {Object} options - Publishing options
10461
+ * @param {string} options.authorName - Author name
10462
+ * @param {string} options.authorId - Author ID
10463
+ * @param {string} options.description - Dashboard description
10464
+ * @param {string[]} options.tags - Tags
10465
+ * @param {string} options.icon - Icon name
10466
+ * @param {string} options.githubUser - GitHub user/org for registry scope
10467
+ * @param {string} options.category - Registry category
10468
+ * @param {Object} widgetRegistry - WidgetRegistry instance
10469
+ * @returns {Promise<Object>} Result with success, manifest, and filePath
10470
+ */
10471
+ async function prepareDashboardForPublish$1(
10472
+ win,
10473
+ appId,
10474
+ workspaceId,
10475
+ options = {},
10476
+ widgetRegistry = null,
10477
+ ) {
10478
+ try {
10479
+ const { generateRegistryManifest } = dashboardConfigUtils$1;
10480
+
10481
+ // 1. Read workspace
10482
+ const filename = path.join(
10483
+ app.getPath("userData"),
10484
+ appName,
10485
+ appId,
10486
+ configFilename,
10487
+ );
10488
+ const workspacesArray = getFileContents(filename);
10489
+ const workspace = workspacesArray.find(
10490
+ (w) => w.id === workspaceId || w.id === Number(workspaceId),
10491
+ );
10492
+
10493
+ if (!workspace) {
10494
+ return {
10495
+ success: false,
10496
+ error: `Workspace not found: ${workspaceId}`,
10497
+ };
10498
+ }
10499
+
10500
+ // 2. Check shareable flag — imported dashboards cannot be published
10501
+ if (workspace._dashboardConfig && workspace._dashboardConfig.shareable === false) {
10502
+ return {
10503
+ success: false,
10504
+ error: "This dashboard was imported and cannot be published. Only dashboards you created can be shared.",
10505
+ };
10506
+ }
10507
+
10508
+ const layout = workspace.layout || [];
10509
+
10510
+ // 3. Build the dashboard config (reuse export logic)
10511
+ const componentNames = collectComponentNames(layout);
10512
+ const eventWiring = extractEventWiring(layout);
10513
+ const widgets = buildWidgetDependencies(componentNames, widgetRegistry);
10514
+ const providers = buildProviderRequirements(componentNames, widgetRegistry);
10515
+
10516
+ const dashboardConfig = applyDefaults({
10517
+ schemaVersion: CURRENT_SCHEMA_VERSION,
10518
+ name: workspace.name || workspace.label || "Dashboard",
10519
+ description: options.description || "",
10520
+ author: {
10521
+ name: options.authorName || "",
10522
+ id: options.authorId || "",
10523
+ },
10524
+ shareable: true,
10525
+ tags: options.tags || [],
10526
+ icon: options.icon || "grip",
10527
+ workspace: {
10528
+ id: workspace.id,
10529
+ name: workspace.name,
10530
+ type: workspace.type || "workspace",
10531
+ label: workspace.label || workspace.name,
10532
+ version: workspace.version || 1,
10533
+ layout,
10534
+ menuId: workspace.menuId || 1,
10535
+ },
10536
+ widgets,
10537
+ providers,
10538
+ eventWiring,
10539
+ });
10540
+
10541
+ // 4. Validate the config
10542
+ const validation = validateDashboardConfig(dashboardConfig);
10543
+ if (!validation.valid) {
10544
+ return {
10545
+ success: false,
10546
+ error: `Generated config is invalid: ${validation.errors.join(", ")}`,
10547
+ };
10548
+ }
10549
+
10550
+ // 5. Verify all widgets exist in the registry
10551
+ const { fetchRegistryIndex } = registryController$1;
10552
+ let registryPackages = [];
10553
+ try {
10554
+ const index = await fetchRegistryIndex();
10555
+ registryPackages = index.packages || [];
10556
+ } catch (err) {
10557
+ return {
10558
+ success: false,
10559
+ error: `Cannot verify widgets in registry: ${err.message}`,
10560
+ };
10561
+ }
10562
+
10563
+ const registryNames = new Set(registryPackages.map((p) => p.name));
10564
+ const missingFromRegistry = widgets
10565
+ .filter((w) => w.required !== false && !registryNames.has(w.package))
10566
+ .map((w) => w.package);
10567
+
10568
+ if (missingFromRegistry.length > 0) {
10569
+ return {
10570
+ success: false,
10571
+ error: `Required widgets not found in registry: ${missingFromRegistry.join(", ")}. Publish them first.`,
10572
+ };
10573
+ }
10574
+
10575
+ // 6. Generate registry manifest
10576
+ const manifest = generateRegistryManifest(dashboardConfig, {
10577
+ githubUser: options.githubUser || options.authorId || "",
10578
+ category: options.category || "general",
10579
+ repository: options.repository || "",
10580
+ });
10581
+
10582
+ // 7. Show save dialog for the publish package
10583
+ const sanitizedName = manifest.name;
10584
+ const { canceled, filePath } = await dialog.showSaveDialog(win, {
10585
+ title: "Save Dashboard Package for Registry",
10586
+ defaultPath: path.join(
10587
+ app.getPath("desktop"),
10588
+ `${sanitizedName}-v${manifest.version}.zip`,
10589
+ ),
10590
+ filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
10591
+ });
10592
+
10593
+ if (canceled || !filePath) {
10594
+ return { success: false, canceled: true };
10595
+ }
10596
+
10597
+ // 8. Create ZIP with manifest and dashboard config
10598
+ const zip = new AdmZip();
10599
+ zip.addFile("manifest.json", Buffer.from(JSON.stringify(manifest, null, 2), "utf-8"));
10600
+ zip.addFile(
10601
+ `${sanitizedName}.dashboard.json`,
10602
+ Buffer.from(JSON.stringify(dashboardConfig, null, 2), "utf-8"),
10603
+ );
10604
+ zip.writeZip(filePath);
10605
+
10606
+ console.log(
10607
+ `[DashboardConfigController] Prepared publish package: ${filePath}`,
10608
+ );
10609
+
10610
+ return {
10611
+ success: true,
10612
+ filePath,
10613
+ manifest,
10614
+ config: dashboardConfig,
10615
+ };
10616
+ } catch (error) {
10617
+ console.error(
10618
+ "[DashboardConfigController] Error preparing dashboard for publish:",
10619
+ error,
10620
+ );
10621
+ return {
10622
+ success: false,
10623
+ error: error.message,
10624
+ };
10625
+ }
10626
+ }
10627
+
10394
10628
  var dashboardConfigController$1 = {
10395
10629
  exportDashboardConfig: exportDashboardConfig$1,
10396
10630
  importDashboardConfig: importDashboardConfig$1,
10397
10631
  installDashboardFromRegistry: installDashboardFromRegistry$1,
10398
10632
  checkCompatibility: checkCompatibility$1,
10633
+ prepareDashboardForPublish: prepareDashboardForPublish$1,
10399
10634
  };
10400
10635
 
10401
10636
  /**
@@ -10489,6 +10724,7 @@ const {
10489
10724
  importDashboardConfig,
10490
10725
  installDashboardFromRegistry,
10491
10726
  checkCompatibility,
10727
+ prepareDashboardForPublish,
10492
10728
  } = dashboardConfigController$1;
10493
10729
 
10494
10730
  var controller = {
@@ -10536,6 +10772,7 @@ var controller = {
10536
10772
  importDashboardConfig,
10537
10773
  installDashboardFromRegistry,
10538
10774
  checkCompatibility,
10775
+ prepareDashboardForPublish,
10539
10776
  };
10540
10777
 
10541
10778
  const { ipcRenderer: ipcRenderer$i } = require$$0$1;
@@ -11916,6 +12153,7 @@ const {
11916
12153
  DASHBOARD_CONFIG_IMPORT,
11917
12154
  DASHBOARD_CONFIG_INSTALL,
11918
12155
  DASHBOARD_CONFIG_COMPATIBILITY,
12156
+ DASHBOARD_CONFIG_PUBLISH,
11919
12157
  } = events$8;
11920
12158
 
11921
12159
  const dashboardConfigApi$2 = {
@@ -11972,6 +12210,23 @@ const dashboardConfigApi$2 = {
11972
12210
  appId,
11973
12211
  dashboardWidgets,
11974
12212
  }),
12213
+
12214
+ /**
12215
+ * Prepare a dashboard for publishing to the registry.
12216
+ * Validates shareable status, checks widgets exist in registry,
12217
+ * generates manifest, and saves a publish-ready ZIP.
12218
+ *
12219
+ * @param {string} appId - Application identifier
12220
+ * @param {number|string} workspaceId - Workspace to publish
12221
+ * @param {Object} options - Publishing options (authorName, authorId, description, tags, icon, githubUser, category)
12222
+ * @returns {Promise<Object>} Result with success, manifest, filePath
12223
+ */
12224
+ prepareDashboardForPublish: (appId, workspaceId, options = {}) =>
12225
+ ipcRenderer$1.invoke(DASHBOARD_CONFIG_PUBLISH, {
12226
+ appId,
12227
+ workspaceId,
12228
+ options,
12229
+ }),
11975
12230
  };
11976
12231
 
11977
12232
  var dashboardConfigApi_1 = dashboardConfigApi$2;