@trops/dash-core 0.1.443 → 0.1.445

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.
@@ -30829,10 +30829,73 @@ const openaiController$1 = {
30829
30829
 
30830
30830
  var openaiController_1 = openaiController$1;
30831
30831
 
30832
+ /**
30833
+ * upsertMenuItem.js
30834
+ *
30835
+ * Pure function that upserts a menu item into a list. Used by
30836
+ * `menuItemsController.saveMenuItemForApplication` so the controller
30837
+ * can stay free of business logic and the upsert is unit-testable
30838
+ * without mocking Electron.
30839
+ *
30840
+ * Behavior:
30841
+ * - Replace any existing entry with the same id (string-coerced
30842
+ * match) instead of appending a duplicate.
30843
+ * - Heal pre-existing dupes already in the list. Walks from the
30844
+ * END so the LAST entry per id wins — that matches the user's
30845
+ * most recent intent (which would be the one they last saved).
30846
+ *
30847
+ * Without this, a dashboard install path that re-saves an existing
30848
+ * folder (e.g. when the publisher's menuId matches the user's
30849
+ * local folder id) creates a second record with the same id but
30850
+ * different icon, and the sidebar nav renders both.
30851
+ *
30852
+ * @param {Array} items - existing menu items list
30853
+ * @param {Object} menuItem - item to upsert
30854
+ * @returns {Array} new list (input is not mutated)
30855
+ */
30856
+
30857
+ function upsertMenuItem$1(items, menuItem) {
30858
+ // Step 1: heal pre-existing duplicates. Walk from the END so the
30859
+ // LAST entry per id wins (matches "user's most recent intent").
30860
+ const filtered = (Array.isArray(items) ? items : []).filter(
30861
+ (mi) => mi !== null,
30862
+ );
30863
+ const seen = new Set();
30864
+ const healed = [];
30865
+ for (let i = filtered.length - 1; i >= 0; i -= 1) {
30866
+ const m = filtered[i];
30867
+ if (!m || m.id === undefined || m.id === null) {
30868
+ healed.unshift(m);
30869
+ continue;
30870
+ }
30871
+ const key = String(m.id);
30872
+ if (seen.has(key)) continue;
30873
+ seen.add(key);
30874
+ healed.unshift(m);
30875
+ }
30876
+ // Step 2: upsert the new item against the healed list.
30877
+ if (menuItem && menuItem.id !== undefined && menuItem.id !== null) {
30878
+ const existingIdx = healed.findIndex(
30879
+ (mi) => mi && String(mi.id) === String(menuItem.id),
30880
+ );
30881
+ if (existingIdx >= 0) {
30882
+ healed[existingIdx] = { ...healed[existingIdx], ...menuItem };
30883
+ } else {
30884
+ healed.push(menuItem);
30885
+ }
30886
+ } else if (menuItem) {
30887
+ healed.push(menuItem);
30888
+ }
30889
+ return healed;
30890
+ }
30891
+
30892
+ var upsertMenuItem_1 = { upsertMenuItem: upsertMenuItem$1 };
30893
+
30832
30894
  const { app: app$5 } = require$$0$1;
30833
30895
  const path$7 = require$$1$2;
30834
30896
  const { writeFileSync } = require$$0$2;
30835
30897
  const { getFileContents: getFileContents$2 } = file;
30898
+ const { upsertMenuItem } = upsertMenuItem_1;
30836
30899
 
30837
30900
  const configFilename$1 = "menuItems.json";
30838
30901
  const appName$2 = "Dashboard";
@@ -30840,38 +30903,20 @@ const appName$2 = "Dashboard";
30840
30903
  const menuItemsController$1 = {
30841
30904
  saveMenuItemForApplication: (win, appId, menuItem) => {
30842
30905
  try {
30843
- // filename to the pages file (live pages)
30844
30906
  const filename = path$7.join(
30845
30907
  app$5.getPath("userData"),
30846
30908
  appName$2,
30847
30909
  appId,
30848
30910
  configFilename$1,
30849
30911
  );
30850
- const menuItemsArray = getFileContents$2(filename);
30851
-
30852
- menuItemsArray.filter((mi) => mi !== null);
30853
-
30854
- // add the menuItems object to the file
30855
- menuItemsArray.push(menuItem);
30856
-
30857
- // write the new pages configuration back to the file
30858
- writeFileSync(filename, JSON.stringify(menuItemsArray, null, 2));
30859
-
30912
+ const raw = getFileContents$2(filename) || [];
30913
+ const deduped = upsertMenuItem(raw, menuItem);
30914
+ writeFileSync(filename, JSON.stringify(deduped, null, 2));
30860
30915
  console.log("[menuItemsController] Menu item saved successfully");
30861
-
30862
- // Return the data for ipcMain.handle() - modern promise-based approach
30863
- return {
30864
- menuItems: menuItemsArray,
30865
- success: true,
30866
- };
30916
+ return { menuItems: deduped, success: true };
30867
30917
  } catch (e) {
30868
30918
  console.error("[menuItemsController] Error saving menu item:", e);
30869
- // Return error object with empty menu items array
30870
- return {
30871
- error: true,
30872
- message: e.message,
30873
- menuItems: [],
30874
- };
30919
+ return { error: true, message: e.message, menuItems: [] };
30875
30920
  }
30876
30921
  },
30877
30922
 
@@ -66597,6 +66642,7 @@ async function installDashboardFromRegistry$1(
66597
66642
  appId,
66598
66643
  packageName,
66599
66644
  widgetRegistry = null,
66645
+ installOptions = {},
66600
66646
  ) {
66601
66647
  try {
66602
66648
  // 1. Look up the dashboard package in the registry
@@ -66763,7 +66809,9 @@ async function installDashboardFromRegistry$1(
66763
66809
  };
66764
66810
  }
66765
66811
 
66766
- // 6. Delegate to shared import pipeline
66812
+ // 6. Delegate to shared import pipeline. User overrides (name /
66813
+ // menuId from the install-time options modal) are forwarded so
66814
+ // the workspace is named + filed where the user wants it.
66767
66815
  return await processDashboardConfig(
66768
66816
  win,
66769
66817
  appId,
@@ -66773,6 +66821,9 @@ async function installDashboardFromRegistry$1(
66773
66821
  source: "registry",
66774
66822
  registryPackage: packageName,
66775
66823
  installedVersion: registryPkg.version || null,
66824
+ name: installOptions.name,
66825
+ menuId: installOptions.menuId,
66826
+ themeKey: installOptions.themeKey,
66776
66827
  },
66777
66828
  );
66778
66829
  } catch (error) {
@@ -76386,12 +76437,19 @@ const dashboardConfigApi$2 = {
76386
76437
  *
76387
76438
  * @param {string} appId - Application identifier
76388
76439
  * @param {string} packageName - Registry package name
76440
+ * @param {Object} [options]
76441
+ * @param {string} [options.name] - Override the workspace name
76442
+ * (defaults to the publisher's name). Does NOT change the
76443
+ * published scope.
76444
+ * @param {string|number} [options.menuId] - Override the destination
76445
+ * folder. Defaults to the publisher's menuId.
76389
76446
  * @returns {Promise<Object>} Result with success, workspace, and summary
76390
76447
  */
76391
- installDashboardFromRegistry: (appId, packageName) =>
76448
+ installDashboardFromRegistry: (appId, packageName, options = {}) =>
76392
76449
  ipcRenderer$9.invoke(DASHBOARD_CONFIG_INSTALL, {
76393
76450
  appId,
76394
76451
  packageName,
76452
+ options,
76395
76453
  }),
76396
76454
 
76397
76455
  /**