@trops/dash-core 0.1.399 → 0.1.400

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.
@@ -28082,6 +28082,75 @@ var schedulerController_1 = schedulerController$2;
28082
28082
  let WIDGETS_CACHE_DIR = null;
28083
28083
  let REGISTRY_CONFIG_FILE = null;
28084
28084
 
28085
+ /**
28086
+ * Populate an existing registry entry with componentNames + widgets
28087
+ * metadata derived from the package on disk. Tries, in order:
28088
+ * 1. dash.json's `widgets` array (the canonical manifest)
28089
+ * 2. scanning `widgets/` for *.dash.js files if dash.json is missing
28090
+ * Mutates the entry in place. Safe to call on entries that already
28091
+ * carry the metadata — only fills blanks, never overwrites existing
28092
+ * values except to promote a more complete list.
28093
+ */
28094
+ function enrichEntryFromDisk(entry, pkgPath) {
28095
+ try {
28096
+ const dashJsonPath = path.join(pkgPath, "dash.json");
28097
+ let widgetsMeta = [];
28098
+ if (fs.existsSync(dashJsonPath)) {
28099
+ try {
28100
+ const manifest = JSON.parse(fs.readFileSync(dashJsonPath, "utf8"));
28101
+ if (Array.isArray(manifest.widgets)) widgetsMeta = manifest.widgets;
28102
+ if (!entry.displayName && manifest.displayName)
28103
+ entry.displayName = manifest.displayName;
28104
+ if (!entry.description && manifest.description)
28105
+ entry.description = manifest.description;
28106
+ if (!entry.author && manifest.author) entry.author = manifest.author;
28107
+ if (!entry.version && manifest.version) entry.version = manifest.version;
28108
+ } catch (err) {
28109
+ console.warn(
28110
+ `[WidgetRegistry] Could not parse dash.json at ${dashJsonPath}:`,
28111
+ err.message,
28112
+ );
28113
+ }
28114
+ }
28115
+ // Fallback: scan widgets/*.dash.js if dash.json didn't yield anything.
28116
+ if (widgetsMeta.length === 0) {
28117
+ const widgetsDir = path.join(pkgPath, "widgets");
28118
+ if (fs.existsSync(widgetsDir)) {
28119
+ try {
28120
+ widgetsMeta = fs
28121
+ .readdirSync(widgetsDir)
28122
+ .filter((f) => f.endsWith(".dash.js"))
28123
+ .map((f) => ({ name: f.replace(/\.dash\.js$/, "") }));
28124
+ } catch (_) {
28125
+ /* ignore */
28126
+ }
28127
+ }
28128
+ }
28129
+ if (widgetsMeta.length > 0) {
28130
+ const names = widgetsMeta
28131
+ .map((w) => w && w.name)
28132
+ .filter((n) => typeof n === "string" && n.length > 0);
28133
+ if (
28134
+ names.length >
28135
+ (Array.isArray(entry.componentNames) ? entry.componentNames.length : 0)
28136
+ ) {
28137
+ entry.componentNames = names;
28138
+ }
28139
+ if (
28140
+ widgetsMeta.length >
28141
+ (Array.isArray(entry.widgets) ? entry.widgets.length : 0)
28142
+ ) {
28143
+ entry.widgets = widgetsMeta;
28144
+ }
28145
+ }
28146
+ } catch (err) {
28147
+ console.warn(
28148
+ `[WidgetRegistry] enrichEntryFromDisk failed for ${pkgPath}:`,
28149
+ err.message,
28150
+ );
28151
+ }
28152
+ }
28153
+
28085
28154
  /**
28086
28155
  * Validate ZIP entries to prevent path traversal attacks.
28087
28156
  * Rejects entries containing '..' segments or absolute paths that would
@@ -28282,25 +28351,75 @@ var schedulerController_1 = schedulerController$2;
28282
28351
  this.saveRegistry();
28283
28352
  console.log("[WidgetRegistry] Disk reconciliation complete");
28284
28353
  }
28354
+
28355
+ // Back-fill componentNames / widgets metadata for any entries
28356
+ // that still look stale (e.g. packages written by older install
28357
+ // flows before metadata was tracked). Needed for the "Edit with
28358
+ // AI" reverse lookup to find which package owns a component.
28359
+ this.backfillMetadataFromDisk();
28285
28360
  } catch (err) {
28286
28361
  console.warn("[WidgetRegistry] Reconciliation error:", err.message);
28287
28362
  }
28288
28363
  }
28289
28364
 
28290
28365
  /**
28291
- * Re-register an orphaned widget package found on disk.
28366
+ * Re-register an orphaned widget package found on disk. Reads the
28367
+ * package's dash.json if present so the registry entry carries the
28368
+ * full component list — without this, downstream flows that look up
28369
+ * "which package contains component X?" (e.g. Edit with AI) hit an
28370
+ * empty `componentNames` array and silently fail.
28292
28371
  */
28293
28372
  _reregisterOrphan(pkgId, pkgPath) {
28294
28373
  console.log(`[WidgetRegistry] Re-registering orphaned widget: ${pkgId}`);
28295
28374
  const { scope } = parsePackageId(pkgId);
28296
- this.widgets.set(pkgId, {
28375
+ const entry = {
28297
28376
  name: pkgId,
28298
28377
  packageId: pkgId,
28299
28378
  scope: scope || null,
28300
28379
  path: pkgPath,
28301
28380
  version: null,
28302
28381
  orphaned: true,
28303
- });
28382
+ };
28383
+ enrichEntryFromDisk(entry, pkgPath);
28384
+ this.widgets.set(pkgId, entry);
28385
+ }
28386
+
28387
+ /**
28388
+ * One-time pass over existing registry entries to back-fill missing
28389
+ * component metadata from each package's dash.json / widgets folder.
28390
+ * Needed for entries that were written by an older version of the
28391
+ * install flow before componentNames was tracked — without this,
28392
+ * "Edit with AI" and other reverse-lookups ("which package owns
28393
+ * component X?") can't resolve the package.
28394
+ */
28395
+ backfillMetadataFromDisk() {
28396
+ let changed = false;
28397
+ for (const [pkgId, entry] of this.widgets.entries()) {
28398
+ const needsBackfill =
28399
+ !Array.isArray(entry.componentNames) ||
28400
+ entry.componentNames.length === 0 ||
28401
+ !Array.isArray(entry.widgets) ||
28402
+ entry.widgets.length === 0;
28403
+ if (!needsBackfill) continue;
28404
+ if (!entry.path || !fs.existsSync(entry.path)) continue;
28405
+ const before = {
28406
+ cn: (entry.componentNames || []).length,
28407
+ w: (entry.widgets || []).length,
28408
+ };
28409
+ enrichEntryFromDisk(entry, entry.path);
28410
+ const after = {
28411
+ cn: (entry.componentNames || []).length,
28412
+ w: (entry.widgets || []).length,
28413
+ };
28414
+ if (after.cn !== before.cn || after.w !== before.w) {
28415
+ console.log(
28416
+ `[WidgetRegistry] Back-filled metadata for ${pkgId}: ` +
28417
+ `componentNames ${before.cn} → ${after.cn}, widgets ${before.w} → ${after.w}`,
28418
+ );
28419
+ changed = true;
28420
+ }
28421
+ }
28422
+ if (changed) this.saveRegistry();
28304
28423
  }
28305
28424
 
28306
28425
  /**