@trops/dash-core 0.1.237 → 0.1.240

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.
@@ -26595,6 +26595,46 @@ mcpController$3.exports.refreshGoogleOAuthToken = refreshGoogleOAuthToken;
26595
26595
 
26596
26596
  var mcpControllerExports = mcpController$3.exports;
26597
26597
 
26598
+ /**
26599
+ * Scoped package identity utilities.
26600
+ *
26601
+ * Follows npm convention: "@scope/name" for scoped packages, "name" for bare.
26602
+ */
26603
+
26604
+ /**
26605
+ * Build a canonical package ID from scope + name.
26606
+ * @param {string|null} scope - e.g. "trops" or "@trops"
26607
+ * @param {string} name - bare package name
26608
+ * @returns {string} e.g. "@trops/slack" or "slack"
26609
+ */
26610
+ function toPackageId$1(scope, name) {
26611
+ if (scope) {
26612
+ const normalized = scope.replace(/^@/, "");
26613
+ return `@${normalized}/${name}`;
26614
+ }
26615
+ return name;
26616
+ }
26617
+
26618
+ /**
26619
+ * Parse a package ID into scope + name.
26620
+ * @param {string} id - e.g. "@trops/slack" or "slack"
26621
+ * @returns {{ scope: string|null, name: string }}
26622
+ */
26623
+ function parsePackageId(id) {
26624
+ if (id && id.startsWith("@")) {
26625
+ const slashIdx = id.indexOf("/");
26626
+ if (slashIdx !== -1) {
26627
+ return {
26628
+ scope: id.slice(1, slashIdx),
26629
+ name: id.slice(slashIdx + 1),
26630
+ };
26631
+ }
26632
+ }
26633
+ return { scope: null, name: id };
26634
+ }
26635
+
26636
+ var packageId = { toPackageId: toPackageId$1, parsePackageId };
26637
+
26598
26638
  /**
26599
26639
  * registryController.js
26600
26640
  *
@@ -26609,6 +26649,7 @@ var mcpControllerExports = mcpController$3.exports;
26609
26649
 
26610
26650
  const path$9 = require$$1$2;
26611
26651
  const fs$5 = require$$0$3;
26652
+ const { toPackageId } = packageId;
26612
26653
 
26613
26654
  // Default registry API base URL
26614
26655
  const DEFAULT_REGISTRY_API_URL = "https://main.d919rwhuzp7rj.amplifyapp.com";
@@ -26926,10 +26967,18 @@ async function checkUpdates(installedWidgets = []) {
26926
26967
  const updates = [];
26927
26968
 
26928
26969
  for (const installed of installedWidgets) {
26929
- const pkg = (index.packages || []).find((p) => p.name === installed.name);
26970
+ const installedId = installed.packageId || installed.name;
26971
+ const pkg = (index.packages || []).find((p) => {
26972
+ // Match by scoped ID (e.g. "@trops/slack" === "@trops/slack")
26973
+ const registryId = toPackageId(p.scope, p.name);
26974
+ if (registryId === installedId) return true;
26975
+ // Fallback: bare-name match for pre-migration entries
26976
+ if (p.name === installedId) return true;
26977
+ return false;
26978
+ });
26930
26979
  if (pkg && pkg.version !== installed.version) {
26931
26980
  updates.push({
26932
- name: pkg.name,
26981
+ name: installed.name,
26933
26982
  currentVersion: installed.version,
26934
26983
  latestVersion: pkg.version,
26935
26984
  downloadUrl: pkg.downloadUrl,
@@ -30933,6 +30982,8 @@ var schedulerController_1 = schedulerController$2;
30933
30982
  const { app, ipcMain, BrowserWindow } = require$$0$2;
30934
30983
  const { dynamicWidgetLoader } = dynamicWidgetLoaderExports;
30935
30984
  const { compileWidget, findWidgetsDir } = widgetCompiler$1;
30985
+ const { toPackageId, parsePackageId } = packageId;
30986
+ const { getStoredToken } = registryAuthController$1;
30936
30987
 
30937
30988
  let WIDGETS_CACHE_DIR = null;
30938
30989
  let REGISTRY_CONFIG_FILE = null;
@@ -31041,6 +31092,46 @@ var schedulerController_1 = schedulerController$2;
31041
31092
  console.log(
31042
31093
  `[WidgetRegistry] Loaded ${this.widgets.size} widgets from cache`,
31043
31094
  );
31095
+
31096
+ // Migration: re-key bare-name entries that have scope metadata
31097
+ if (!registryData._scopeMigrated) {
31098
+ let migrated = false;
31099
+ const entries = Array.from(this.widgets.entries());
31100
+ for (const [key, entry] of entries) {
31101
+ if (entry.scope && !key.startsWith("@")) {
31102
+ const scopedId = toPackageId(entry.scope, key);
31103
+
31104
+ // Move folder from widgets/{name}/ to widgets/@{scope}/{name}/
31105
+ const oldPath = path.join(WIDGETS_CACHE_DIR, key);
31106
+ const newPath = path.join(
31107
+ WIDGETS_CACHE_DIR,
31108
+ ...scopedId.split("/"),
31109
+ );
31110
+ if (fs.existsSync(oldPath) && !fs.existsSync(newPath)) {
31111
+ const scopeDir = path.dirname(newPath);
31112
+ if (!fs.existsSync(scopeDir)) {
31113
+ fs.mkdirSync(scopeDir, { recursive: true });
31114
+ }
31115
+ fs.renameSync(oldPath, newPath);
31116
+ console.log(
31117
+ `[WidgetRegistry] Migrated folder: ${key} → ${scopedId}`,
31118
+ );
31119
+ }
31120
+
31121
+ // Re-key in the Map
31122
+ entry.name = scopedId;
31123
+ entry.packageId = scopedId;
31124
+ entry.path = newPath;
31125
+ this.widgets.delete(key);
31126
+ this.widgets.set(scopedId, entry);
31127
+ migrated = true;
31128
+ }
31129
+ }
31130
+ if (migrated) {
31131
+ this.saveRegistry();
31132
+ console.log("[WidgetRegistry] Scope migration complete");
31133
+ }
31134
+ }
31044
31135
  }
31045
31136
  } catch (error) {
31046
31137
  console.error("[WidgetRegistry] Error loading registry:", error);
@@ -31142,7 +31233,8 @@ var schedulerController_1 = schedulerController$2;
31142
31233
  throw new Error(`Local path not found: ${resolvedPath}`);
31143
31234
  }
31144
31235
 
31145
- const widgetPath = path.join(WIDGETS_CACHE_DIR, widgetName);
31236
+ // Scoped names (e.g. "@trops/slack") get nested dirs: widgets/@trops/slack/
31237
+ const widgetPath = path.join(WIDGETS_CACHE_DIR, ...widgetName.split("/"));
31146
31238
 
31147
31239
  if (fs.existsSync(widgetPath)) {
31148
31240
  fs.rmSync(widgetPath, { recursive: true });
@@ -31331,14 +31423,30 @@ var schedulerController_1 = schedulerController$2;
31331
31423
  `[WidgetRegistry] Downloading widget: ${widgetName} from ${downloadUrl}`,
31332
31424
  );
31333
31425
 
31334
- const response = await fetch(downloadUrl);
31426
+ // Add auth header for registry API download endpoints
31427
+ const fetchOpts = {};
31428
+ const registryBase =
31429
+ process.env.DASH_REGISTRY_API_URL ||
31430
+ "https://main.d919rwhuzp7rj.amplifyapp.com";
31431
+ if (
31432
+ downloadUrl.includes(registryBase) ||
31433
+ downloadUrl.includes("/api/packages/")
31434
+ ) {
31435
+ const auth = getStoredToken();
31436
+ if (auth?.token) {
31437
+ fetchOpts.headers = { Authorization: `Bearer ${auth.token}` };
31438
+ }
31439
+ }
31440
+
31441
+ const response = await fetch(downloadUrl, fetchOpts);
31335
31442
  if (!response.ok)
31336
31443
  throw new Error(`Failed to fetch: ${response.statusText}`);
31337
31444
 
31338
31445
  const buffer = await response.arrayBuffer();
31339
31446
  const zip = new AdmZip(Buffer.from(buffer));
31340
31447
 
31341
- const widgetPath = path.join(WIDGETS_CACHE_DIR, widgetName);
31448
+ // Scoped names (e.g. "@trops/slack") get nested dirs: widgets/@trops/slack/
31449
+ const widgetPath = path.join(WIDGETS_CACHE_DIR, ...widgetName.split("/"));
31342
31450
 
31343
31451
  if (fs.existsSync(widgetPath)) {
31344
31452
  fs.rmSync(widgetPath, { recursive: true });
@@ -31432,6 +31540,9 @@ var schedulerController_1 = schedulerController$2;
31432
31540
  widgetEntry.scope = config.scope;
31433
31541
  }
31434
31542
 
31543
+ // Store canonical package ID for update matching
31544
+ widgetEntry.packageId = widgetName;
31545
+
31435
31546
  this.widgets.set(widgetName, widgetEntry);
31436
31547
  this.saveRegistry();
31437
31548
  console.log(`[WidgetRegistry] Registered widget: ${widgetName}`);
@@ -31557,6 +31668,16 @@ var schedulerController_1 = schedulerController$2;
31557
31668
  if (fs.existsSync(widget.path)) {
31558
31669
  fs.rmSync(widget.path, { recursive: true });
31559
31670
  }
31671
+
31672
+ // Clean up empty scope directory (e.g. widgets/@trops/ after removing @trops/slack)
31673
+ const { scope } = parsePackageId(widgetName);
31674
+ if (scope) {
31675
+ const scopeDir = path.join(WIDGETS_CACHE_DIR, `@${scope}`);
31676
+ if (fs.existsSync(scopeDir) && fs.readdirSync(scopeDir).length === 0) {
31677
+ fs.rmdirSync(scopeDir);
31678
+ }
31679
+ }
31680
+
31560
31681
  this.widgets.delete(widgetName);
31561
31682
  this.saveRegistry();
31562
31683
  console.log(`[WidgetRegistry] Uninstalled widget: ${widgetName}`);