@trops/dash-core 0.1.92 → 0.1.93

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.
@@ -606,6 +606,24 @@ var dashboardConfigEvents$1 = {
606
606
  DASHBOARD_CONFIG_PROVIDER_SETUP: DASHBOARD_CONFIG_PROVIDER_SETUP$1,
607
607
  };
608
608
 
609
+ /**
610
+ * Dashboard Ratings Events
611
+ *
612
+ * IPC event constants for dashboard ratings CRUD.
613
+ */
614
+
615
+ const DASHBOARD_RATING_SAVE = "dashboard-rating-save";
616
+ const DASHBOARD_RATING_GET = "dashboard-rating-get";
617
+ const DASHBOARD_RATING_LIST = "dashboard-rating-list";
618
+ const DASHBOARD_RATING_DELETE = "dashboard-rating-delete";
619
+
620
+ var dashboardRatingsEvents$1 = {
621
+ DASHBOARD_RATING_SAVE,
622
+ DASHBOARD_RATING_GET,
623
+ DASHBOARD_RATING_LIST,
624
+ DASHBOARD_RATING_DELETE,
625
+ };
626
+
609
627
  /**
610
628
  * Events
611
629
  *
@@ -628,6 +646,7 @@ const openaiEvents = openaiEvents$1;
628
646
  const llmEvents = llmEvents$1;
629
647
  const clientCacheEvents = clientCacheEvents$1;
630
648
  const dashboardConfigEvents = dashboardConfigEvents$1;
649
+ const dashboardRatingsEvents = dashboardRatingsEvents$1;
631
650
 
632
651
  const publicEvents = {
633
652
  ...dataEvents,
@@ -651,6 +670,7 @@ var events$8 = {
651
670
  ...llmEvents,
652
671
  ...clientCacheEvents,
653
672
  ...dashboardConfigEvents,
673
+ ...dashboardRatingsEvents,
654
674
  };
655
675
 
656
676
  /**
@@ -744,7 +764,7 @@ var secureStoreController$1 = {
744
764
  getData: getData$1,
745
765
  };
746
766
 
747
- const path$e = require$$1$1;
767
+ const path$f = require$$1$1;
748
768
  const {
749
769
  readFileSync,
750
770
  writeFileSync: writeFileSync$4,
@@ -762,7 +782,7 @@ const {
762
782
  function ensureDirectoryExistence$2(filePath) {
763
783
  try {
764
784
  // isDirectory
765
- var dirname = path$e.dirname(filePath);
785
+ var dirname = path$f.dirname(filePath);
766
786
  // check if the directory exists...return true
767
787
  // if not, we can pass in the dirname as the filepath
768
788
  // and check each directory recursively.
@@ -813,7 +833,7 @@ function checkDirectory$1(dir) {
813
833
  * @param {string} filepath path to the file
814
834
  * @returns
815
835
  */
816
- function getFileContents$7(filepath, defaultReturn = []) {
836
+ function getFileContents$8(filepath, defaultReturn = []) {
817
837
  try {
818
838
  // lets first make sure all is there...
819
839
  ensureDirectoryExistence$2(filepath);
@@ -854,7 +874,7 @@ function getFileContents$7(filepath, defaultReturn = []) {
854
874
  }
855
875
  }
856
876
 
857
- function writeToFile$2(filename, data) {
877
+ function writeToFile$3(filename, data) {
858
878
  try {
859
879
  // write the new pages configuration back to the file
860
880
  return writeFileSync$4(filename, data);
@@ -877,7 +897,7 @@ function removeFilesFromDirectory(directory, excludeFiles = []) {
877
897
 
878
898
  for (const file of files) {
879
899
  if (!excludeFiles.includes(file)) {
880
- unlinkSync(path$e.join(directory, file), (err) => {
900
+ unlinkSync(path$f.join(directory, file), (err) => {
881
901
  if (err) throw err;
882
902
  });
883
903
  }
@@ -888,19 +908,19 @@ function removeFilesFromDirectory(directory, excludeFiles = []) {
888
908
 
889
909
  var file = {
890
910
  ensureDirectoryExistence: ensureDirectoryExistence$2,
891
- getFileContents: getFileContents$7,
892
- writeToFile: writeToFile$2,
911
+ getFileContents: getFileContents$8,
912
+ writeToFile: writeToFile$3,
893
913
  removeFilesFromDirectory,
894
914
  checkDirectory: checkDirectory$1,
895
915
  };
896
916
 
897
- const { app: app$8 } = require$$0$1;
898
- const path$d = require$$1$1;
917
+ const { app: app$9 } = require$$0$1;
918
+ const path$e = require$$1$1;
899
919
  const { writeFileSync: writeFileSync$3 } = require$$2;
900
- const { getFileContents: getFileContents$6 } = file;
920
+ const { getFileContents: getFileContents$7 } = file;
901
921
 
902
922
  const configFilename$5 = "workspaces.json";
903
- const appName$6 = "Dashboard";
923
+ const appName$7 = "Dashboard";
904
924
 
905
925
  const workspaceController$1 = {
906
926
  /**
@@ -942,13 +962,13 @@ const workspaceController$1 = {
942
962
  saveWorkspaceForApplication: (win, appId, workspaceObject) => {
943
963
  try {
944
964
  // filename to the pages file (live pages)
945
- const filename = path$d.join(
946
- app$8.getPath("userData"),
947
- appName$6,
965
+ const filename = path$e.join(
966
+ app$9.getPath("userData"),
967
+ appName$7,
948
968
  appId,
949
969
  configFilename$5,
950
970
  );
951
- const workspacesArray = getFileContents$6(filename);
971
+ const workspacesArray = getFileContents$7(filename);
952
972
 
953
973
  // lets check to see if we already have this one!
954
974
  let indexOfExistingItem = null;
@@ -991,13 +1011,13 @@ const workspaceController$1 = {
991
1011
  saveMenuItemsForApplication: (win, appId, menuItems) => {
992
1012
  try {
993
1013
  // filename to the workspaces file
994
- const filename = path$d.join(
995
- app$8.getPath("userData"),
996
- appName$6,
1014
+ const filename = path$e.join(
1015
+ app$9.getPath("userData"),
1016
+ appName$7,
997
1017
  appId,
998
1018
  configFilename$5,
999
1019
  );
1000
- const workspacesArray = getFileContents$6(filename);
1020
+ const workspacesArray = getFileContents$7(filename);
1001
1021
 
1002
1022
  // Update menu items for workspaces
1003
1023
  // This assumes menuItems is an object with workspace IDs as keys
@@ -1040,13 +1060,13 @@ const workspaceController$1 = {
1040
1060
  */
1041
1061
  deleteWorkspaceForApplication: (win, appId, workspaceId) => {
1042
1062
  try {
1043
- const filename = path$d.join(
1044
- app$8.getPath("userData"),
1045
- appName$6,
1063
+ const filename = path$e.join(
1064
+ app$9.getPath("userData"),
1065
+ appName$7,
1046
1066
  appId,
1047
1067
  configFilename$5,
1048
1068
  );
1049
- const workspacesArray = getFileContents$6(filename);
1069
+ const workspacesArray = getFileContents$7(filename);
1050
1070
 
1051
1071
  const filtered = workspacesArray.filter(
1052
1072
  (workspace) => workspace.id !== workspaceId,
@@ -1074,14 +1094,14 @@ const workspaceController$1 = {
1074
1094
 
1075
1095
  listWorkspacesForApplication: (win, appId) => {
1076
1096
  try {
1077
- const filename = path$d.join(
1078
- app$8.getPath("userData"),
1079
- appName$6,
1097
+ const filename = path$e.join(
1098
+ app$9.getPath("userData"),
1099
+ appName$7,
1080
1100
  appId,
1081
1101
  configFilename$5,
1082
1102
  );
1083
1103
 
1084
- const workspacesArray = getFileContents$6(filename);
1104
+ const workspacesArray = getFileContents$7(filename);
1085
1105
  console.log(
1086
1106
  `[workspaceController] Loaded ${workspacesArray.length} workspaces for appId: ${appId}`,
1087
1107
  );
@@ -1102,13 +1122,13 @@ const workspaceController$1 = {
1102
1122
 
1103
1123
  listMenuItemsForApplication: (win, appId) => {
1104
1124
  try {
1105
- const filename = path$d.join(
1106
- app$8.getPath("userData"),
1107
- appName$6,
1125
+ const filename = path$e.join(
1126
+ app$9.getPath("userData"),
1127
+ appName$7,
1108
1128
  appId,
1109
1129
  configFilename$5,
1110
1130
  );
1111
- const workspacesArray = getFileContents$6(filename);
1131
+ const workspacesArray = getFileContents$7(filename);
1112
1132
 
1113
1133
  // Extract unique menu items from workspaces
1114
1134
  // Each workspace can have a menuId, we need to build the menu items list
@@ -1146,13 +1166,13 @@ const workspaceController$1 = {
1146
1166
 
1147
1167
  var workspaceController_1 = workspaceController$1;
1148
1168
 
1149
- const { app: app$7 } = require$$0$1;
1150
- const path$c = require$$1$1;
1169
+ const { app: app$8 } = require$$0$1;
1170
+ const path$d = require$$1$1;
1151
1171
  const { writeFileSync: writeFileSync$2 } = require$$2;
1152
- const { getFileContents: getFileContents$5 } = file;
1172
+ const { getFileContents: getFileContents$6 } = file;
1153
1173
 
1154
1174
  const configFilename$4 = "themes.json";
1155
- const appName$5 = "Dashboard";
1175
+ const appName$6 = "Dashboard";
1156
1176
 
1157
1177
  const themeController$1 = {
1158
1178
  /**
@@ -1167,13 +1187,13 @@ const themeController$1 = {
1167
1187
  saveThemeForApplication: (win, appId, name, obj) => {
1168
1188
  try {
1169
1189
  // filename to the pages file (live pages)
1170
- const filename = path$c.join(
1171
- app$7.getPath("userData"),
1172
- appName$5,
1190
+ const filename = path$d.join(
1191
+ app$8.getPath("userData"),
1192
+ appName$6,
1173
1193
  appId,
1174
1194
  configFilename$4,
1175
1195
  );
1176
- const data = getFileContents$5(filename, {});
1196
+ const data = getFileContents$6(filename, {});
1177
1197
 
1178
1198
  // Add/update the theme based on the name
1179
1199
  if (name in data === false) {
@@ -1213,14 +1233,14 @@ const themeController$1 = {
1213
1233
  */
1214
1234
  listThemesForApplication: (win, appId) => {
1215
1235
  try {
1216
- const filename = path$c.join(
1217
- app$7.getPath("userData"),
1218
- appName$5,
1236
+ const filename = path$d.join(
1237
+ app$8.getPath("userData"),
1238
+ appName$6,
1219
1239
  appId,
1220
1240
  configFilename$4,
1221
1241
  );
1222
1242
 
1223
- const data = getFileContents$5(filename, {});
1243
+ const data = getFileContents$6(filename, {});
1224
1244
 
1225
1245
  console.log(
1226
1246
  "[themeController] Loading themes from:",
@@ -1255,13 +1275,13 @@ const themeController$1 = {
1255
1275
  */
1256
1276
  deleteThemeForApplication: (win, appId, themeKey) => {
1257
1277
  try {
1258
- const filename = path$c.join(
1259
- app$7.getPath("userData"),
1260
- appName$5,
1278
+ const filename = path$d.join(
1279
+ app$8.getPath("userData"),
1280
+ appName$6,
1261
1281
  appId,
1262
1282
  configFilename$4,
1263
1283
  );
1264
- const data = getFileContents$5(filename, {});
1284
+ const data = getFileContents$6(filename, {});
1265
1285
 
1266
1286
  if (themeKey in data) {
1267
1287
  delete data[themeKey];
@@ -1302,8 +1322,8 @@ var xmlParser = require$$3;
1302
1322
  var JSONStream$1 = require$$4;
1303
1323
  const stream = require$$5;
1304
1324
  var csv = require$$6;
1305
- const path$b = require$$1$1;
1306
- const { app: app$6 } = require$$0$1;
1325
+ const path$c = require$$1$1;
1326
+ const { app: app$7 } = require$$0$1;
1307
1327
  const { ensureDirectoryExistence: ensureDirectoryExistence$1 } = file;
1308
1328
 
1309
1329
  const TRANSFORM_APP_NAME = "Dashboard";
@@ -1591,18 +1611,18 @@ let Transform$1 = class Transform {
1591
1611
  }
1592
1612
 
1593
1613
  // Validate file paths are within app data directory
1594
- const appDataDir = path$b.join(app$6.getPath("userData"), TRANSFORM_APP_NAME);
1595
- const resolvedFilepath = path$b.resolve(filepath);
1596
- const resolvedOutFilepath = path$b.resolve(outFilepath);
1614
+ const appDataDir = path$c.join(app$7.getPath("userData"), TRANSFORM_APP_NAME);
1615
+ const resolvedFilepath = path$c.resolve(filepath);
1616
+ const resolvedOutFilepath = path$c.resolve(outFilepath);
1597
1617
 
1598
- if (!resolvedFilepath.startsWith(appDataDir + path$b.sep)) {
1618
+ if (!resolvedFilepath.startsWith(appDataDir + path$c.sep)) {
1599
1619
  return reject(
1600
1620
  new Error(
1601
1621
  "Input file path must be within the application data directory",
1602
1622
  ),
1603
1623
  );
1604
1624
  }
1605
- if (!resolvedOutFilepath.startsWith(appDataDir + path$b.sep)) {
1625
+ if (!resolvedOutFilepath.startsWith(appDataDir + path$c.sep)) {
1606
1626
  return reject(
1607
1627
  new Error(
1608
1628
  "Output file path must be within the application data directory",
@@ -3460,18 +3480,18 @@ async function extractColorsFromImageURL$2(url, toDirectory) {
3460
3480
 
3461
3481
  var color = { extractColorsFromImageURL: extractColorsFromImageURL$2 };
3462
3482
 
3463
- const { app: app$5 } = require$$0$1;
3483
+ const { app: app$6 } = require$$0$1;
3464
3484
  var fs$7 = require$$2;
3465
- const path$a = require$$1$1;
3485
+ const path$b = require$$1$1;
3466
3486
  const events$5 = events$8;
3467
- const { getFileContents: getFileContents$4, writeToFile: writeToFile$1 } = file;
3487
+ const { getFileContents: getFileContents$5, writeToFile: writeToFile$2 } = file;
3468
3488
 
3469
3489
  // Convert Json to Csv
3470
3490
  const ObjectsToCsv = require$$5$1;
3471
3491
  const Transform = transform;
3472
3492
  const { extractColorsFromImageURL: extractColorsFromImageURL$1 } = color;
3473
3493
  const https = require$$8;
3474
- const appName$4 = "Dashboard";
3494
+ const appName$5 = "Dashboard";
3475
3495
 
3476
3496
  const dataController$1 = {
3477
3497
  /**
@@ -3485,16 +3505,16 @@ const dataController$1 = {
3485
3505
  convertJsonToCsvFile: (win, appId, jsonObject, toFilename = "test.csv") => {
3486
3506
  try {
3487
3507
  // filename to the pages file (live pages)
3488
- const filename = path$a.join(
3489
- app$5.getPath("userData"),
3490
- appName$4,
3508
+ const filename = path$b.join(
3509
+ app$6.getPath("userData"),
3510
+ appName$5,
3491
3511
  appId,
3492
3512
  "data",
3493
3513
  toFilename,
3494
3514
  );
3495
3515
 
3496
3516
  // make sure the file exists...
3497
- const fileContents = getFileContents$4(filename, "");
3517
+ const fileContents = getFileContents$5(filename, "");
3498
3518
 
3499
3519
  const csv = new ObjectsToCsv(jsonObject);
3500
3520
 
@@ -3613,9 +3633,9 @@ const dataController$1 = {
3613
3633
  }
3614
3634
 
3615
3635
  // Validate toFilepath is within the app data directory
3616
- const appDataDir = path$a.join(app$5.getPath("userData"), appName$4);
3617
- const resolvedFilepath = path$a.resolve(toFilepath);
3618
- if (!resolvedFilepath.startsWith(appDataDir + path$a.sep)) {
3636
+ const appDataDir = path$b.join(app$6.getPath("userData"), appName$5);
3637
+ const resolvedFilepath = path$b.resolve(toFilepath);
3638
+ if (!resolvedFilepath.startsWith(appDataDir + path$b.sep)) {
3619
3639
  throw new Error(
3620
3640
  "File path must be within the application data directory",
3621
3641
  );
@@ -3762,9 +3782,9 @@ const dataController$1 = {
3762
3782
  try {
3763
3783
  if (data) {
3764
3784
  // filename to the pages file (live pages)
3765
- const toFilename = path$a.join(
3766
- app$5.getPath("userData"),
3767
- appName$4,
3785
+ const toFilename = path$b.join(
3786
+ app$6.getPath("userData"),
3787
+ appName$5,
3768
3788
  "data",
3769
3789
  filename,
3770
3790
  );
@@ -3772,7 +3792,7 @@ const dataController$1 = {
3772
3792
  //console.log("saving to file ", toFilename);
3773
3793
 
3774
3794
  // // call this to make sure the directory structure exists
3775
- let fileContents = getFileContents$4(toFilename, returnEmpty);
3795
+ let fileContents = getFileContents$5(toFilename, returnEmpty);
3776
3796
  if (fileContents === null || fileContents === "") {
3777
3797
  fileContents = JSON.stringify(returnEmpty);
3778
3798
  }
@@ -3788,7 +3808,7 @@ const dataController$1 = {
3788
3808
  const tempWriteContents = JSON.parse(fileContents);
3789
3809
  tempWriteContents[stamp] = data;
3790
3810
  writeContents = JSON.stringify(tempWriteContents);
3791
- writeToFile$1(toFilename, writeContents);
3811
+ writeToFile$2(toFilename, writeContents);
3792
3812
  }
3793
3813
 
3794
3814
  if (JSON.stringify(returnEmpty) === "[]") {
@@ -3797,20 +3817,20 @@ const dataController$1 = {
3797
3817
  writeContents = JSON.stringify(tempWriteContents);
3798
3818
  // writeContents = JSON.parse(fileContents);
3799
3819
  // writeContents.push({ [stamp]: data });
3800
- writeToFile$1(toFilename, writeContents);
3820
+ writeToFile$2(toFilename, writeContents);
3801
3821
  }
3802
3822
  } else {
3803
3823
  // overwrite existing
3804
3824
  writeContents = JSON.stringify(data);
3805
3825
  if (JSON.stringify(returnEmpty) === "{}") {
3806
- writeToFile$1(
3826
+ writeToFile$2(
3807
3827
  toFilename,
3808
3828
  writeContents,
3809
3829
  // JSON.stringify({ [stamp]: data })
3810
3830
  );
3811
3831
  }
3812
3832
  if (JSON.stringify(returnEmpty) === "[]") {
3813
- writeToFile$1(
3833
+ writeToFile$2(
3814
3834
  toFilename,
3815
3835
  writeContents,
3816
3836
  // JSON.stringify([{ [stamp]: data }])
@@ -3844,15 +3864,15 @@ const dataController$1 = {
3844
3864
  try {
3845
3865
  if (filename) {
3846
3866
  // filename to the pages file (live pages)
3847
- const fromFilename = path$a.join(
3848
- app$5.getPath("userData"),
3849
- appName$4,
3867
+ const fromFilename = path$b.join(
3868
+ app$6.getPath("userData"),
3869
+ appName$5,
3850
3870
  "data",
3851
3871
  filename,
3852
3872
  );
3853
3873
  console.log("reading from file ", fromFilename, returnIfEmpty);
3854
3874
  // make sure the file exists...
3855
- const fileContents = getFileContents$4(fromFilename, returnIfEmpty);
3875
+ const fileContents = getFileContents$5(fromFilename, returnIfEmpty);
3856
3876
 
3857
3877
  console.log("file contents ", fileContents, fromFilename);
3858
3878
 
@@ -3922,9 +3942,9 @@ const dataController$1 = {
3922
3942
  try {
3923
3943
  console.log(url);
3924
3944
  const fileExtension = ".jpg";
3925
- const filename = path$a.join(
3926
- app$5.getPath("userData"),
3927
- appName$4,
3945
+ const filename = path$b.join(
3946
+ app$6.getPath("userData"),
3947
+ appName$5,
3928
3948
  "@algolia/dash-electron",
3929
3949
  "data",
3930
3950
  "imageExtract" + fileExtension,
@@ -3947,13 +3967,13 @@ var dataController_1 = dataController$1;
3947
3967
  * settingsController
3948
3968
  */
3949
3969
 
3950
- const { app: app$4 } = require$$0$1;
3951
- const path$9 = require$$1$1;
3970
+ const { app: app$5 } = require$$0$1;
3971
+ const path$a = require$$1$1;
3952
3972
  const fs$6 = require$$2;
3953
- const { getFileContents: getFileContents$3, writeToFile } = file;
3973
+ const { getFileContents: getFileContents$4, writeToFile: writeToFile$1 } = file;
3954
3974
 
3955
3975
  const configFilename$3 = "settings.json";
3956
- const appName$3 = "Dashboard";
3976
+ const appName$4 = "Dashboard";
3957
3977
 
3958
3978
  // Helper function to recursively copy directory
3959
3979
  function copyDirectory(source, destination) {
@@ -3963,8 +3983,8 @@ function copyDirectory(source, destination) {
3963
3983
 
3964
3984
  const files = fs$6.readdirSync(source);
3965
3985
  for (const file of files) {
3966
- const srcPath = path$9.join(source, file);
3967
- const destPath = path$9.join(destination, file);
3986
+ const srcPath = path$a.join(source, file);
3987
+ const destPath = path$a.join(destination, file);
3968
3988
  const stat = fs$6.lstatSync(srcPath);
3969
3989
 
3970
3990
  // Skip symlinks to prevent following links to sensitive files
@@ -3992,12 +4012,12 @@ const settingsController$1 = {
3992
4012
  try {
3993
4013
  if (data) {
3994
4014
  // <appId>/settings.json
3995
- const filename = path$9.join(
3996
- app$4.getPath("userData"),
3997
- appName$3,
4015
+ const filename = path$a.join(
4016
+ app$5.getPath("userData"),
4017
+ appName$4,
3998
4018
  configFilename$3,
3999
4019
  );
4000
- writeToFile(filename, JSON.stringify(data, null, 2));
4020
+ writeToFile$1(filename, JSON.stringify(data, null, 2));
4001
4021
  console.log("[settingsController] Settings saved successfully");
4002
4022
  // Return the data for ipcMain.handle() - modern promise-based approach
4003
4023
  return {
@@ -4028,13 +4048,13 @@ const settingsController$1 = {
4028
4048
  getSettingsForApplication: (win) => {
4029
4049
  try {
4030
4050
  // <appId>/settings.json
4031
- const filename = path$9.join(
4032
- app$4.getPath("userData"),
4033
- appName$3,
4051
+ const filename = path$a.join(
4052
+ app$5.getPath("userData"),
4053
+ appName$4,
4034
4054
  configFilename$3,
4035
4055
  );
4036
4056
  // make sure the file exists...
4037
- const fileContents = getFileContents$3(filename, {});
4057
+ const fileContents = getFileContents$4(filename, {});
4038
4058
  console.log("[settingsController] Settings loaded successfully");
4039
4059
  // Return the data for ipcMain.handle() - modern promise-based approach
4040
4060
  return {
@@ -4059,15 +4079,15 @@ const settingsController$1 = {
4059
4079
  */
4060
4080
  getDataDirectory: (win) => {
4061
4081
  try {
4062
- const settingsPath = path$9.join(
4063
- app$4.getPath("userData"),
4064
- appName$3,
4082
+ const settingsPath = path$a.join(
4083
+ app$5.getPath("userData"),
4084
+ appName$4,
4065
4085
  configFilename$3,
4066
4086
  );
4067
- const settings = getFileContents$3(settingsPath, {});
4087
+ const settings = getFileContents$4(settingsPath, {});
4068
4088
  const userDataDir =
4069
4089
  settings.userDataDirectory ||
4070
- path$9.join(app$4.getPath("userData"), appName$3);
4090
+ path$a.join(app$5.getPath("userData"), appName$4);
4071
4091
 
4072
4092
  console.log("[settingsController] Data directory retrieved successfully");
4073
4093
  // Return the data for ipcMain.handle() - modern promise-based approach
@@ -4104,14 +4124,14 @@ const settingsController$1 = {
4104
4124
  }
4105
4125
 
4106
4126
  // Update settings
4107
- const settingsPath = path$9.join(
4108
- app$4.getPath("userData"),
4109
- appName$3,
4127
+ const settingsPath = path$a.join(
4128
+ app$5.getPath("userData"),
4129
+ appName$4,
4110
4130
  configFilename$3,
4111
4131
  );
4112
- const settings = getFileContents$3(settingsPath, {});
4132
+ const settings = getFileContents$4(settingsPath, {});
4113
4133
  settings.userDataDirectory = newPath;
4114
- writeToFile(settingsPath, JSON.stringify(settings, null, 2));
4134
+ writeToFile$1(settingsPath, JSON.stringify(settings, null, 2));
4115
4135
 
4116
4136
  console.log("[settingsController] Data directory set successfully");
4117
4137
  // Return the data for ipcMain.handle() - modern promise-based approach
@@ -4138,20 +4158,20 @@ const settingsController$1 = {
4138
4158
  migrateDataDirectory: (win, oldPath, newPath) => {
4139
4159
  try {
4140
4160
  // Resolve paths to prevent traversal
4141
- const resolvedOldPath = path$9.resolve(oldPath);
4142
- const resolvedNewPath = path$9.resolve(newPath);
4161
+ const resolvedOldPath = path$a.resolve(oldPath);
4162
+ const resolvedNewPath = path$a.resolve(newPath);
4143
4163
 
4144
4164
  // Validate oldPath is the current configured data directory
4145
- const settingsCheckPath = path$9.join(
4146
- app$4.getPath("userData"),
4147
- appName$3,
4165
+ const settingsCheckPath = path$a.join(
4166
+ app$5.getPath("userData"),
4167
+ appName$4,
4148
4168
  configFilename$3,
4149
4169
  );
4150
- const currentSettings = getFileContents$3(settingsCheckPath, {});
4170
+ const currentSettings = getFileContents$4(settingsCheckPath, {});
4151
4171
  const currentDataDir =
4152
4172
  currentSettings.userDataDirectory ||
4153
- path$9.join(app$4.getPath("userData"), appName$3);
4154
- if (resolvedOldPath !== path$9.resolve(currentDataDir)) {
4173
+ path$a.join(app$5.getPath("userData"), appName$4);
4174
+ if (resolvedOldPath !== path$a.resolve(currentDataDir)) {
4155
4175
  throw new Error("Source path must be the current data directory");
4156
4176
  }
4157
4177
 
@@ -4187,14 +4207,14 @@ const settingsController$1 = {
4187
4207
  copyDirectory(resolvedOldPath, resolvedNewPath);
4188
4208
 
4189
4209
  // Update settings to use new path
4190
- const settingsPath = path$9.join(
4191
- app$4.getPath("userData"),
4192
- appName$3,
4210
+ const settingsPath = path$a.join(
4211
+ app$5.getPath("userData"),
4212
+ appName$4,
4193
4213
  configFilename$3,
4194
4214
  );
4195
- const settings = getFileContents$3(settingsPath, {});
4215
+ const settings = getFileContents$4(settingsPath, {});
4196
4216
  settings.userDataDirectory = resolvedNewPath;
4197
- writeToFile(settingsPath, JSON.stringify(settings, null, 2));
4217
+ writeToFile$1(settingsPath, JSON.stringify(settings, null, 2));
4198
4218
 
4199
4219
  console.log("[settingsController] Data directory migrated successfully");
4200
4220
  // Return the data for ipcMain.handle() - modern promise-based approach
@@ -4801,14 +4821,14 @@ function requireProviderController () {
4801
4821
  return providerController_1;
4802
4822
  }
4803
4823
 
4804
- const { app: app$3 } = require$$0$1;
4805
- const path$8 = require$$1$1;
4824
+ const { app: app$4 } = require$$0$1;
4825
+ const path$9 = require$$1$1;
4806
4826
  const { writeFileSync: writeFileSync$1 } = require$$2;
4807
4827
  const events$4 = events$8;
4808
- const { getFileContents: getFileContents$2 } = file;
4828
+ const { getFileContents: getFileContents$3 } = file;
4809
4829
 
4810
4830
  const configFilename$2 = "layouts.json";
4811
- const appName$2 = "Dashboard";
4831
+ const appName$3 = "Dashboard";
4812
4832
 
4813
4833
  const layoutController$1 = {
4814
4834
  /**
@@ -4822,13 +4842,13 @@ const layoutController$1 = {
4822
4842
  saveLayoutForApplication: (win, appId, layoutObject) => {
4823
4843
  try {
4824
4844
  // filename to the pages file (live pages)
4825
- const filename = path$8.join(
4826
- app$3.getPath("userData"),
4827
- appName$2,
4845
+ const filename = path$9.join(
4846
+ app$4.getPath("userData"),
4847
+ appName$3,
4828
4848
  appId,
4829
4849
  configFilename$2,
4830
4850
  );
4831
- const layoutsArray = getFileContents$2(filename);
4851
+ const layoutsArray = getFileContents$3(filename);
4832
4852
 
4833
4853
  // add the pageObject to the pages file
4834
4854
  layoutsArray.push(layoutObject);
@@ -4855,13 +4875,13 @@ const layoutController$1 = {
4855
4875
  */
4856
4876
  listLayoutsForApplication: (win, appId) => {
4857
4877
  try {
4858
- const filename = path$8.join(
4859
- app$3.getPath("userData"),
4860
- appName$2,
4878
+ const filename = path$9.join(
4879
+ app$4.getPath("userData"),
4880
+ appName$3,
4861
4881
  appId,
4862
4882
  configFilename$2,
4863
4883
  );
4864
- const layoutsArray = getFileContents$2(filename);
4884
+ const layoutsArray = getFileContents$3(filename);
4865
4885
  win.webContents.send(events$4.LAYOUT_LIST_COMPLETE, {
4866
4886
  layouts: layoutsArray,
4867
4887
  });
@@ -4898,7 +4918,7 @@ const {
4898
4918
  const {
4899
4919
  StreamableHTTPClientTransport,
4900
4920
  } = require$$2$3;
4901
- const path$7 = require$$1$1;
4921
+ const path$8 = require$$1$1;
4902
4922
  const fs$5 = require$$2;
4903
4923
 
4904
4924
  /**
@@ -5315,7 +5335,7 @@ const mcpController$2 = {
5315
5335
  }
5316
5336
 
5317
5337
  // Interpolate {{MCP_DIR}} in args to resolve local MCP server scripts
5318
- const mcpDir = path$7.join(__dirname, "..", "mcp");
5338
+ const mcpDir = path$8.join(__dirname, "..", "mcp");
5319
5339
  for (let i = 0; i < args.length; i++) {
5320
5340
  if (
5321
5341
  typeof args[i] === "string" &&
@@ -5690,7 +5710,7 @@ const mcpController$2 = {
5690
5710
  */
5691
5711
  getCatalog: (win) => {
5692
5712
  try {
5693
- const catalogPath = path$7.join(
5713
+ const catalogPath = path$8.join(
5694
5714
  __dirname,
5695
5715
  "..",
5696
5716
  "mcp",
@@ -5802,7 +5822,7 @@ const mcpController$2 = {
5802
5822
  }
5803
5823
 
5804
5824
  // Interpolate {{MCP_DIR}} in authCommand args (same as startServer)
5805
- const mcpDir = path$7.join(__dirname, "..", "mcp");
5825
+ const mcpDir = path$8.join(__dirname, "..", "mcp");
5806
5826
  const resolvedArgs = (authCommand.args || []).map((arg) =>
5807
5827
  typeof arg === "string" && arg.includes("{{MCP_DIR}}")
5808
5828
  ? arg.replace(/\{\{MCP_DIR\}\}/g, mcpDir)
@@ -5898,7 +5918,7 @@ var mcpControllerExports = mcpController$3.exports;
5898
5918
  * - Support two-level browsing: packages (bundles) and widgets within packages
5899
5919
  */
5900
5920
 
5901
- const path$6 = require$$1$1;
5921
+ const path$7 = require$$1$1;
5902
5922
  const fs$4 = require$$2;
5903
5923
 
5904
5924
  // Default registry URL (GitHub Pages)
@@ -5915,7 +5935,7 @@ let cacheTimestamp = 0;
5915
5935
  * Get the local test registry path for dev mode
5916
5936
  */
5917
5937
  function getTestRegistryPath() {
5918
- return path$6.join(__dirname, "..", "registry", "test-registry-index.json");
5938
+ return path$7.join(__dirname, "..", "registry", "test-registry-index.json");
5919
5939
  }
5920
5940
 
5921
5941
  /**
@@ -6175,7 +6195,7 @@ var registryController$1 = {
6175
6195
  var fs$3 = require$$2;
6176
6196
  var JSONStream = require$$4;
6177
6197
  const algoliasearch$1 = require$$2$4;
6178
- const path$5 = require$$3$2;
6198
+ const path$6 = require$$3$2;
6179
6199
  const { ensureDirectoryExistence, checkDirectory } = file;
6180
6200
 
6181
6201
  let AlgoliaIndex$1 = class AlgoliaIndex {
@@ -6282,7 +6302,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
6282
6302
  if (err) reject(err);
6283
6303
  if (files) {
6284
6304
  files.forEach((file) => {
6285
- fs$3.unlinkSync(path$5.join(directoryPath, file));
6305
+ fs$3.unlinkSync(path$6.join(directoryPath, file));
6286
6306
  });
6287
6307
  resolve();
6288
6308
  }
@@ -6305,7 +6325,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
6305
6325
  let results = [];
6306
6326
  for (const fileIndex in files) {
6307
6327
  // for each file lets read the file and then push to algolia
6308
- const pathToBatch = path$5.join(batchFilepath, files[fileIndex]);
6328
+ const pathToBatch = path$6.join(batchFilepath, files[fileIndex]);
6309
6329
  const fileContents = await this.readFile(pathToBatch);
6310
6330
  if (fileContents) {
6311
6331
  if ("data" in fileContents && "filepath" in fileContents) {
@@ -6759,25 +6779,25 @@ const openaiController$1 = {
6759
6779
 
6760
6780
  var openaiController_1 = openaiController$1;
6761
6781
 
6762
- const { app: app$2 } = require$$0$1;
6763
- const path$4 = require$$1$1;
6782
+ const { app: app$3 } = require$$0$1;
6783
+ const path$5 = require$$1$1;
6764
6784
  const { writeFileSync } = require$$2;
6765
- const { getFileContents: getFileContents$1 } = file;
6785
+ const { getFileContents: getFileContents$2 } = file;
6766
6786
 
6767
6787
  const configFilename$1 = "menuItems.json";
6768
- const appName$1 = "Dashboard";
6788
+ const appName$2 = "Dashboard";
6769
6789
 
6770
6790
  const menuItemsController$1 = {
6771
6791
  saveMenuItemForApplication: (win, appId, menuItem) => {
6772
6792
  try {
6773
6793
  // filename to the pages file (live pages)
6774
- const filename = path$4.join(
6775
- app$2.getPath("userData"),
6776
- appName$1,
6794
+ const filename = path$5.join(
6795
+ app$3.getPath("userData"),
6796
+ appName$2,
6777
6797
  appId,
6778
6798
  configFilename$1,
6779
6799
  );
6780
- const menuItemsArray = getFileContents$1(filename);
6800
+ const menuItemsArray = getFileContents$2(filename);
6781
6801
 
6782
6802
  menuItemsArray.filter((mi) => mi !== null);
6783
6803
 
@@ -6807,13 +6827,13 @@ const menuItemsController$1 = {
6807
6827
 
6808
6828
  listMenuItemsForApplication: (win, appId) => {
6809
6829
  try {
6810
- const filename = path$4.join(
6811
- app$2.getPath("userData"),
6812
- appName$1,
6830
+ const filename = path$5.join(
6831
+ app$3.getPath("userData"),
6832
+ appName$2,
6813
6833
  appId,
6814
6834
  configFilename$1,
6815
6835
  );
6816
- const menuItemsArray = getFileContents$1(filename);
6836
+ const menuItemsArray = getFileContents$2(filename);
6817
6837
  const filtered = menuItemsArray.filter((mi) => mi !== null);
6818
6838
  // Return the data for ipcMain.handle() - modern promise-based approach
6819
6839
  return {
@@ -6833,14 +6853,14 @@ const menuItemsController$1 = {
6833
6853
 
6834
6854
  var menuItemsController_1 = menuItemsController$1;
6835
6855
 
6836
- const path$3 = require$$1$1;
6837
- const { app: app$1 } = require$$0$1;
6856
+ const path$4 = require$$1$1;
6857
+ const { app: app$2 } = require$$0$1;
6838
6858
 
6839
6859
  const pluginController$1 = {
6840
6860
  install: (win, packageName, filepath) => {
6841
6861
  try {
6842
- const rootPath = path$3.join(
6843
- app$1.getPath("userData"),
6862
+ const rootPath = path$4.join(
6863
+ app$2.getPath("userData"),
6844
6864
  "plugins",
6845
6865
  packageName,
6846
6866
  );
@@ -8681,7 +8701,7 @@ var dynamicWidgetLoader$2 = {exports: {}};
8681
8701
  */
8682
8702
 
8683
8703
  const fs$1 = require$$2;
8684
- const path$2 = require$$1$1;
8704
+ const path$3 = require$$1$1;
8685
8705
 
8686
8706
  /**
8687
8707
  * Find the widgets/ directory, handling nested ZIP extraction.
@@ -8696,13 +8716,13 @@ const path$2 = require$$1$1;
8696
8716
  * @returns {string|null} Path to the widgets/ directory, or null
8697
8717
  */
8698
8718
  function findWidgetsDir$1(widgetPath) {
8699
- const direct = path$2.join(widgetPath, "widgets");
8719
+ const direct = path$3.join(widgetPath, "widgets");
8700
8720
  if (fs$1.existsSync(direct)) {
8701
8721
  return direct;
8702
8722
  }
8703
8723
 
8704
8724
  // Check configs/ directory (used by packageZip.js for distributed widgets)
8705
- const configs = path$2.join(widgetPath, "configs");
8725
+ const configs = path$3.join(widgetPath, "configs");
8706
8726
  if (fs$1.existsSync(configs)) {
8707
8727
  return configs;
8708
8728
  }
@@ -8719,7 +8739,7 @@ function findWidgetsDir$1(widgetPath) {
8719
8739
  );
8720
8740
 
8721
8741
  for (const subdir of subdirs) {
8722
- const nested = path$2.join(widgetPath, subdir.name, "widgets");
8742
+ const nested = path$3.join(widgetPath, subdir.name, "widgets");
8723
8743
  if (fs$1.existsSync(nested)) {
8724
8744
  console.log(`[WidgetCompiler] Found nested widgets/ at ${nested}`);
8725
8745
  return nested;
@@ -8768,14 +8788,14 @@ async function compileWidget(widgetPath) {
8768
8788
  // Compute relative path from the entry file (in widgetPath) to widgetsDir,
8769
8789
  // since widgetsDir may be nested (e.g., ./weather-widget/widgets/).
8770
8790
  const relWidgetsDir =
8771
- "./" + path$2.relative(widgetPath, widgetsDir).split(path$2.sep).join("/");
8791
+ "./" + path$3.relative(widgetPath, widgetsDir).split(path$3.sep).join("/");
8772
8792
  const imports = [];
8773
8793
  const exportParts = [];
8774
8794
 
8775
8795
  for (const dashFile of dashFiles) {
8776
8796
  const componentName = dashFile.replace(".dash.js", "");
8777
8797
  const componentFile = `${componentName}.js`;
8778
- const componentFilePath = path$2.join(widgetsDir, componentFile);
8798
+ const componentFilePath = path$3.join(widgetsDir, componentFile);
8779
8799
  const hasComponent = fs$1.existsSync(componentFilePath);
8780
8800
 
8781
8801
  // Import the config (always)
@@ -8802,9 +8822,9 @@ async function compileWidget(widgetPath) {
8802
8822
  const entryContent = [...imports, "", ...exportParts, ""].join("\n");
8803
8823
 
8804
8824
  // Write temporary entry file in the widget root
8805
- const entryPath = path$2.join(widgetPath, "__compile_entry.js");
8806
- const distDir = path$2.join(widgetPath, "dist");
8807
- const outPath = path$2.join(distDir, "index.cjs.js");
8825
+ const entryPath = path$3.join(widgetPath, "__compile_entry.js");
8826
+ const distDir = path$3.join(widgetPath, "dist");
8827
+ const outPath = path$3.join(distDir, "index.cjs.js");
8808
8828
 
8809
8829
  try {
8810
8830
  // Ensure dist/ directory exists
@@ -8881,7 +8901,7 @@ var widgetCompiler$1 = { compileWidget, findWidgetsDir: findWidgetsDir$1 };
8881
8901
  */
8882
8902
 
8883
8903
  const fs = require$$2;
8884
- const path$1 = require$$1$1;
8904
+ const path$2 = require$$1$1;
8885
8905
  const vm = require$$2$5;
8886
8906
  const { findWidgetsDir } = widgetCompiler$1;
8887
8907
 
@@ -8922,9 +8942,9 @@ class DynamicWidgetLoader {
8922
8942
  );
8923
8943
 
8924
8944
  const widgetsDir =
8925
- findWidgetsDir(widgetPath) || path$1.join(widgetPath, "widgets");
8926
- const componentPath = path$1.join(widgetsDir, `${componentName}.js`);
8927
- const configPath = path$1.join(widgetsDir, `${componentName}.dash.js`);
8945
+ findWidgetsDir(widgetPath) || path$2.join(widgetPath, "widgets");
8946
+ const componentPath = path$2.join(widgetsDir, `${componentName}.js`);
8947
+ const configPath = path$2.join(widgetsDir, `${componentName}.dash.js`);
8928
8948
 
8929
8949
  if (!fs.existsSync(componentPath)) {
8930
8950
  throw new Error(`Component file not found: ${componentPath}`);
@@ -10053,10 +10073,10 @@ var widgetRegistryExports = widgetRegistry$1.exports;
10053
10073
  * applies event wiring. (Import is implemented in DASH-13.)
10054
10074
  */
10055
10075
 
10056
- const { app, dialog } = require$$0$1;
10057
- const path = require$$1$1;
10076
+ const { app: app$1, dialog } = require$$0$1;
10077
+ const path$1 = require$$1$1;
10058
10078
  const AdmZip = require$$3$3;
10059
- const { getFileContents } = file;
10079
+ const { getFileContents: getFileContents$1 } = file;
10060
10080
  const {
10061
10081
  validateDashboardConfig,
10062
10082
  applyDefaults,
@@ -10072,7 +10092,7 @@ const {
10072
10092
  const { searchRegistry, getPackage } = registryController$1;
10073
10093
 
10074
10094
  const configFilename = "workspaces.json";
10075
- const appName = "Dashboard";
10095
+ const appName$1 = "Dashboard";
10076
10096
 
10077
10097
  /**
10078
10098
  * Export a workspace as a .dashboard.json config inside a ZIP file.
@@ -10095,13 +10115,13 @@ async function exportDashboardConfig$1(
10095
10115
  ) {
10096
10116
  try {
10097
10117
  // 1. Read workspace from workspaces.json
10098
- const filename = path.join(
10099
- app.getPath("userData"),
10100
- appName,
10118
+ const filename = path$1.join(
10119
+ app$1.getPath("userData"),
10120
+ appName$1,
10101
10121
  appId,
10102
10122
  configFilename,
10103
10123
  );
10104
- const workspacesArray = getFileContents(filename);
10124
+ const workspacesArray = getFileContents$1(filename);
10105
10125
  const workspace = workspacesArray.find(
10106
10126
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
10107
10127
  );
@@ -10164,7 +10184,7 @@ async function exportDashboardConfig$1(
10164
10184
 
10165
10185
  const { canceled, filePath } = await dialog.showSaveDialog(win, {
10166
10186
  title: "Export Dashboard as ZIP",
10167
- defaultPath: path.join(app.getPath("desktop"), `${sanitizedName}.zip`),
10187
+ defaultPath: path$1.join(app$1.getPath("desktop"), `${sanitizedName}.zip`),
10168
10188
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
10169
10189
  });
10170
10190
 
@@ -10238,7 +10258,7 @@ async function importDashboardConfig$1(win, appId, widgetRegistry = null) {
10238
10258
  const zip = new AdmZip(zipPath);
10239
10259
 
10240
10260
  // Validate ZIP entries for path traversal
10241
- const tempDir = path.join(app.getPath("temp"), "dash-import");
10261
+ const tempDir = path$1.join(app$1.getPath("temp"), "dash-import");
10242
10262
  const { validateZipEntries } = widgetRegistryExports;
10243
10263
  validateZipEntries(zip, tempDir);
10244
10264
 
@@ -10514,7 +10534,7 @@ async function installDashboardFromRegistry$1(
10514
10534
  const zip = new AdmZip(Buffer.from(buffer));
10515
10535
 
10516
10536
  // 3. Validate ZIP entries
10517
- const tempDir = path.join(app.getPath("temp"), "dash-registry-import");
10537
+ const tempDir = path$1.join(app$1.getPath("temp"), "dash-registry-import");
10518
10538
  const { validateZipEntries } = widgetRegistryExports;
10519
10539
  validateZipEntries(zip, tempDir);
10520
10540
 
@@ -10642,13 +10662,13 @@ async function prepareDashboardForPublish$1(
10642
10662
  const { generateRegistryManifest } = dashboardConfigUtils$1;
10643
10663
 
10644
10664
  // 1. Read workspace
10645
- const filename = path.join(
10646
- app.getPath("userData"),
10647
- appName,
10665
+ const filename = path$1.join(
10666
+ app$1.getPath("userData"),
10667
+ appName$1,
10648
10668
  appId,
10649
10669
  configFilename,
10650
10670
  );
10651
- const workspacesArray = getFileContents(filename);
10671
+ const workspacesArray = getFileContents$1(filename);
10652
10672
  const workspace = workspacesArray.find(
10653
10673
  (w) => w.id === workspaceId || w.id === Number(workspaceId),
10654
10674
  );
@@ -10746,8 +10766,8 @@ async function prepareDashboardForPublish$1(
10746
10766
  const sanitizedName = manifest.name;
10747
10767
  const { canceled, filePath } = await dialog.showSaveDialog(win, {
10748
10768
  title: "Save Dashboard Package for Registry",
10749
- defaultPath: path.join(
10750
- app.getPath("desktop"),
10769
+ defaultPath: path$1.join(
10770
+ app$1.getPath("desktop"),
10751
10771
  `${sanitizedName}-v${manifest.version}.zip`,
10752
10772
  ),
10753
10773
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
@@ -10847,13 +10867,13 @@ async function checkDashboardUpdatesForApp$1(appId) {
10847
10867
  const { fetchRegistryIndex } = registryController$1;
10848
10868
 
10849
10869
  try {
10850
- const filename = path.join(
10851
- app.getPath("userData"),
10852
- appName,
10870
+ const filename = path$1.join(
10871
+ app$1.getPath("userData"),
10872
+ appName$1,
10853
10873
  appId,
10854
10874
  configFilename,
10855
10875
  );
10856
- const workspaces = getFileContents(filename) || [];
10876
+ const workspaces = getFileContents$1(filename) || [];
10857
10877
 
10858
10878
  const index = await fetchRegistryIndex();
10859
10879
  const registryPackages = index.packages || [];
@@ -10941,6 +10961,164 @@ clientCache$1.registerFactory("openai", (credentials) => {
10941
10961
  return new OpenAI({ apiKey: credentials.apiKey });
10942
10962
  });
10943
10963
 
10964
+ /**
10965
+ * dashboardRatingsUtils.js
10966
+ *
10967
+ * Pure utility functions for dashboard ratings logic.
10968
+ * No Electron or file I/O dependencies — safe to test anywhere.
10969
+ */
10970
+
10971
+ /**
10972
+ * Validate and build a rating entry.
10973
+ *
10974
+ * @param {string} packageName - Dashboard package name
10975
+ * @param {Object} rating - Rating input
10976
+ * @param {number} rating.stars - 1-5 star rating
10977
+ * @param {string} [rating.review] - Optional text review
10978
+ * @returns {Object} { success, rating, error }
10979
+ */
10980
+ function validateAndBuildRating$1(packageName, rating = {}) {
10981
+ if (!packageName) {
10982
+ return { success: false, error: "Package name is required" };
10983
+ }
10984
+
10985
+ const stars = Number(rating.stars);
10986
+ if (!stars || stars < 1 || stars > 5 || !Number.isInteger(stars)) {
10987
+ return {
10988
+ success: false,
10989
+ error: "Stars must be an integer between 1 and 5",
10990
+ };
10991
+ }
10992
+
10993
+ const entry = {
10994
+ stars,
10995
+ review:
10996
+ typeof rating.review === "string" ? rating.review.slice(0, 1000) : "",
10997
+ ratedAt: new Date().toISOString(),
10998
+ };
10999
+
11000
+ return { success: true, rating: entry };
11001
+ }
11002
+
11003
+ /**
11004
+ * Enrich packages with user rating data (pure function).
11005
+ *
11006
+ * @param {Array} packages - Registry packages
11007
+ * @param {Object} ratings - Map of packageName → rating data
11008
+ * @returns {Array} Packages with userRating field added
11009
+ */
11010
+ function enrichWithRatings$1(packages, ratings) {
11011
+ return packages.map((pkg) => ({
11012
+ ...pkg,
11013
+ userRating: ratings[pkg.name] || null,
11014
+ }));
11015
+ }
11016
+
11017
+ var dashboardRatingsUtils = {
11018
+ validateAndBuildRating: validateAndBuildRating$1,
11019
+ enrichWithRatings: enrichWithRatings$1,
11020
+ };
11021
+
11022
+ /**
11023
+ * dashboardRatingsController.js
11024
+ *
11025
+ * Local storage for dashboard ratings and reviews.
11026
+ * Stores user ratings per dashboard package in a JSON file.
11027
+ * Runs in the Electron main process.
11028
+ */
11029
+
11030
+ const { app } = require$$0$1;
11031
+ const path = require$$1$1;
11032
+ const { getFileContents, writeToFile } = file;
11033
+ const {
11034
+ validateAndBuildRating,
11035
+ enrichWithRatings,
11036
+ } = dashboardRatingsUtils;
11037
+
11038
+ const ratingsFilename = "dashboard-ratings.json";
11039
+ const appName = "Dashboard";
11040
+
11041
+ /**
11042
+ * Get the ratings file path for an app.
11043
+ */
11044
+ function getRatingsPath(appId) {
11045
+ return path.join(app.getPath("userData"), appName, appId, ratingsFilename);
11046
+ }
11047
+
11048
+ /**
11049
+ * Read all ratings from disk.
11050
+ */
11051
+ function readRatings(appId) {
11052
+ const filepath = getRatingsPath(appId);
11053
+ return getFileContents(filepath, {});
11054
+ }
11055
+
11056
+ /**
11057
+ * Write ratings to disk.
11058
+ */
11059
+ function writeRatings(appId, ratings) {
11060
+ const filepath = getRatingsPath(appId);
11061
+ writeToFile(filepath, JSON.stringify(ratings, null, 2));
11062
+ }
11063
+
11064
+ /**
11065
+ * Save or update a rating for a dashboard package.
11066
+ */
11067
+ function saveDashboardRating$1(appId, packageName, rating = {}) {
11068
+ const result = validateAndBuildRating(packageName, rating);
11069
+ if (!result.success) return result;
11070
+
11071
+ const ratings = readRatings(appId);
11072
+ ratings[packageName] = result.rating;
11073
+ writeRatings(appId, ratings);
11074
+
11075
+ return { success: true, rating: ratings[packageName] };
11076
+ }
11077
+
11078
+ /**
11079
+ * Get the user's rating for a specific dashboard package.
11080
+ */
11081
+ function getDashboardRating$1(appId, packageName) {
11082
+ const ratings = readRatings(appId);
11083
+ return ratings[packageName] || null;
11084
+ }
11085
+
11086
+ /**
11087
+ * Get all dashboard ratings.
11088
+ */
11089
+ function listDashboardRatings$1(appId) {
11090
+ return readRatings(appId);
11091
+ }
11092
+
11093
+ /**
11094
+ * Delete a rating for a dashboard package.
11095
+ */
11096
+ function deleteDashboardRating$1(appId, packageName) {
11097
+ const ratings = readRatings(appId);
11098
+ if (!ratings[packageName]) {
11099
+ return { success: false, error: "No rating found for this package" };
11100
+ }
11101
+ delete ratings[packageName];
11102
+ writeRatings(appId, ratings);
11103
+ return { success: true };
11104
+ }
11105
+
11106
+ /**
11107
+ * Enrich registry packages with local rating data.
11108
+ */
11109
+ function enrichPackagesWithRatings$1(packages, appId) {
11110
+ const ratings = readRatings(appId);
11111
+ return enrichWithRatings(packages, ratings);
11112
+ }
11113
+
11114
+ var dashboardRatingsController = {
11115
+ saveDashboardRating: saveDashboardRating$1,
11116
+ getDashboardRating: getDashboardRating$1,
11117
+ listDashboardRatings: listDashboardRatings$1,
11118
+ deleteDashboardRating: deleteDashboardRating$1,
11119
+ enrichPackagesWithRatings: enrichPackagesWithRatings$1,
11120
+ };
11121
+
10944
11122
  /**
10945
11123
  * Controller exports.
10946
11124
  */
@@ -11010,6 +11188,13 @@ const {
11010
11188
  checkDashboardUpdatesForApp,
11011
11189
  getProviderSetupManifest,
11012
11190
  } = dashboardConfigController$1;
11191
+ const {
11192
+ saveDashboardRating,
11193
+ getDashboardRating,
11194
+ listDashboardRatings,
11195
+ deleteDashboardRating,
11196
+ enrichPackagesWithRatings,
11197
+ } = dashboardRatingsController;
11013
11198
 
11014
11199
  var controller = {
11015
11200
  showDialog,
@@ -11060,6 +11245,11 @@ var controller = {
11060
11245
  getDashboardPreview,
11061
11246
  checkDashboardUpdatesForApp,
11062
11247
  getProviderSetupManifest,
11248
+ saveDashboardRating,
11249
+ getDashboardRating,
11250
+ listDashboardRatings,
11251
+ deleteDashboardRating,
11252
+ enrichPackagesWithRatings,
11063
11253
  };
11064
11254
 
11065
11255
  const { ipcRenderer: ipcRenderer$i } = require$$0$1;