@trops/dash-core 0.1.422 → 0.1.425
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.
- package/dist/electron/index.js +188 -28
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +525 -177
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +590 -224
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -28520,13 +28520,16 @@ var schedulerController_1 = schedulerController$2;
|
|
|
28520
28520
|
backfillMetadataFromDisk() {
|
|
28521
28521
|
let changed = false;
|
|
28522
28522
|
for (const [pkgId, entry] of this.widgets.entries()) {
|
|
28523
|
-
const needsBackfill =
|
|
28524
|
-
!Array.isArray(entry.componentNames) ||
|
|
28525
|
-
entry.componentNames.length === 0 ||
|
|
28526
|
-
!Array.isArray(entry.widgets) ||
|
|
28527
|
-
entry.widgets.length === 0;
|
|
28528
|
-
if (!needsBackfill) continue;
|
|
28529
28523
|
if (!entry.path || !fs.existsSync(entry.path)) continue;
|
|
28524
|
+
// Always re-enrich from disk — don't gate on whether the cache
|
|
28525
|
+
// looks populated. A package's `dash.json` can gain new widgets
|
|
28526
|
+
// between sessions (author edits, AI-builder adds, etc.), and
|
|
28527
|
+
// skipping enrichment here is exactly how publish ends up
|
|
28528
|
+
// attributing a shared component to the wrong package:
|
|
28529
|
+
// `@scope/bundle` appears to not provide it (stale cache),
|
|
28530
|
+
// so a singleton `@scope/name` wins by elimination.
|
|
28531
|
+
// `enrichEntryFromDisk` already guards against shrinking the
|
|
28532
|
+
// list, so re-running it on every entry is idempotent.
|
|
28530
28533
|
const before = {
|
|
28531
28534
|
cn: (entry.componentNames || []).length,
|
|
28532
28535
|
w: (entry.widgets || []).length,
|
|
@@ -28538,7 +28541,7 @@ var schedulerController_1 = schedulerController$2;
|
|
|
28538
28541
|
};
|
|
28539
28542
|
if (after.cn !== before.cn || after.w !== before.w) {
|
|
28540
28543
|
console.log(
|
|
28541
|
-
`[WidgetRegistry]
|
|
28544
|
+
`[WidgetRegistry] Refreshed metadata for ${pkgId}: ` +
|
|
28542
28545
|
`componentNames ${before.cn} → ${after.cn}, widgets ${before.w} → ${after.w}`,
|
|
28543
28546
|
);
|
|
28544
28547
|
changed = true;
|
|
@@ -62937,6 +62940,15 @@ var properties = {
|
|
|
62937
62940
|
"1.0.0"
|
|
62938
62941
|
]
|
|
62939
62942
|
},
|
|
62943
|
+
version: {
|
|
62944
|
+
type: "string",
|
|
62945
|
+
description: "Package version (semver) of the published dashboard. Distinct from workspace.version (integer schema revision). Bumped on each republish.",
|
|
62946
|
+
pattern: "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$",
|
|
62947
|
+
examples: [
|
|
62948
|
+
"1.0.0",
|
|
62949
|
+
"1.2.3-beta"
|
|
62950
|
+
]
|
|
62951
|
+
},
|
|
62940
62952
|
name: {
|
|
62941
62953
|
type: "string",
|
|
62942
62954
|
description: "Display name of the dashboard",
|
|
@@ -63602,16 +63614,87 @@ function stripScopePrefix(fullName, scope) {
|
|
|
63602
63614
|
* @returns {Array} Widget dependency objects for the dashboard config
|
|
63603
63615
|
*/
|
|
63604
63616
|
function buildWidgetDependencies$1(
|
|
63605
|
-
|
|
63617
|
+
componentNamesOrRefs,
|
|
63606
63618
|
widgetRegistry = null,
|
|
63607
63619
|
componentConfigs = null,
|
|
63608
63620
|
) {
|
|
63609
63621
|
const widgets = [];
|
|
63610
63622
|
const seen = new Set();
|
|
63611
63623
|
|
|
63612
|
-
|
|
63613
|
-
|
|
63614
|
-
|
|
63624
|
+
// Accept both the legacy string-array shape and the new
|
|
63625
|
+
// `{component, packageId}` ref shape. Refs carry the exact source
|
|
63626
|
+
// package recorded at widget-add time — no guessing needed. Legacy
|
|
63627
|
+
// layout items that predate packageId pass `packageId: null` and
|
|
63628
|
+
// still fall through to the registry fallback.
|
|
63629
|
+
const refs = (componentNamesOrRefs || []).map((entry) =>
|
|
63630
|
+
typeof entry === "string"
|
|
63631
|
+
? { component: entry, packageId: null }
|
|
63632
|
+
: { component: entry.component, packageId: entry.packageId || null },
|
|
63633
|
+
);
|
|
63634
|
+
|
|
63635
|
+
// Pre-index the installed widgets by packageId for O(1) lookup when
|
|
63636
|
+
// refs specify one. The secondary map by component name is used for
|
|
63637
|
+
// the legacy/fallback path where packageId isn't known. When a
|
|
63638
|
+
// shared component appears without a packageId, rank candidates by
|
|
63639
|
+
// how many of THIS dashboard's widgets they provide so the
|
|
63640
|
+
// best-fit bundle wins over a single-widget package that happens
|
|
63641
|
+
// to share the name.
|
|
63642
|
+
const installedWidgets = widgetRegistry ? widgetRegistry.getWidgets() : [];
|
|
63643
|
+
const byPackageId = new Map();
|
|
63644
|
+
const byComponentName = new Map();
|
|
63645
|
+
for (const w of installedWidgets) {
|
|
63646
|
+
// packageId on the registry entry is usually `@scope/name`; also
|
|
63647
|
+
// index by the bare `scope/name` form since callers occasionally
|
|
63648
|
+
// strip the @.
|
|
63649
|
+
const ids = new Set();
|
|
63650
|
+
if (w.packageId) ids.add(w.packageId);
|
|
63651
|
+
if (w.name) ids.add(w.name);
|
|
63652
|
+
if (w.scope && w.name) {
|
|
63653
|
+
const bareScope = String(w.scope).replace(/^@/, "");
|
|
63654
|
+
const bareName = stripScopePrefix(w.name, w.scope);
|
|
63655
|
+
ids.add(`@${bareScope}/${bareName}`);
|
|
63656
|
+
ids.add(`${bareScope}/${bareName}`);
|
|
63657
|
+
}
|
|
63658
|
+
for (const id of ids) {
|
|
63659
|
+
if (id && !byPackageId.has(id)) byPackageId.set(id, w);
|
|
63660
|
+
}
|
|
63661
|
+
if (Array.isArray(w.componentNames)) {
|
|
63662
|
+
for (const cn of w.componentNames) {
|
|
63663
|
+
if (!byComponentName.has(cn)) byComponentName.set(cn, []);
|
|
63664
|
+
byComponentName.get(cn).push(w);
|
|
63665
|
+
}
|
|
63666
|
+
}
|
|
63667
|
+
}
|
|
63668
|
+
|
|
63669
|
+
const requestedComponentSet = new Set(refs.map((r) => r.component));
|
|
63670
|
+
const rankCandidates = (candidates) =>
|
|
63671
|
+
[...candidates].sort((a, b) => {
|
|
63672
|
+
const aMatches = (a.componentNames || []).filter((n) =>
|
|
63673
|
+
requestedComponentSet.has(n),
|
|
63674
|
+
).length;
|
|
63675
|
+
const bMatches = (b.componentNames || []).filter((n) =>
|
|
63676
|
+
requestedComponentSet.has(n),
|
|
63677
|
+
).length;
|
|
63678
|
+
if (aMatches !== bMatches) return bMatches - aMatches;
|
|
63679
|
+
return (b.componentNames?.length || 0) - (a.componentNames?.length || 0);
|
|
63680
|
+
});
|
|
63681
|
+
|
|
63682
|
+
const applyRegistryMatch = (w, name, resolved) => {
|
|
63683
|
+
if (!resolved.scope && w.scope) resolved.scope = w.scope;
|
|
63684
|
+
if (!resolved.packageName || resolved.packageName === name) {
|
|
63685
|
+
resolved.packageName =
|
|
63686
|
+
stripScopePrefix(w.name, w.scope || resolved.scope) || "";
|
|
63687
|
+
}
|
|
63688
|
+
resolved.version = w.version || "*";
|
|
63689
|
+
resolved.author =
|
|
63690
|
+
typeof w.author === "string" ? w.author : w.author?.name || "";
|
|
63691
|
+
};
|
|
63692
|
+
|
|
63693
|
+
for (const ref of refs) {
|
|
63694
|
+
const name = ref.component;
|
|
63695
|
+
const dedupeKey = `${name}|${ref.packageId || ""}`;
|
|
63696
|
+
if (seen.has(dedupeKey)) continue;
|
|
63697
|
+
seen.add(dedupeKey);
|
|
63615
63698
|
|
|
63616
63699
|
let scope = "";
|
|
63617
63700
|
let packageName = "";
|
|
@@ -63627,23 +63710,34 @@ function buildWidgetDependencies$1(
|
|
|
63627
63710
|
widgetName = parts[2];
|
|
63628
63711
|
}
|
|
63629
63712
|
|
|
63630
|
-
|
|
63631
|
-
|
|
63632
|
-
|
|
63633
|
-
|
|
63634
|
-
|
|
63635
|
-
|
|
63636
|
-
|
|
63637
|
-
|
|
63638
|
-
|
|
63639
|
-
|
|
63640
|
-
author =
|
|
63641
|
-
typeof w.author === "string" ? w.author : w.author?.name || "";
|
|
63642
|
-
break;
|
|
63643
|
-
}
|
|
63713
|
+
const resolved = { scope, packageName, version, author };
|
|
63714
|
+
|
|
63715
|
+
// Authoritative path: the layout item told us exactly which
|
|
63716
|
+
// package this widget came from. Look it up directly. No guessing.
|
|
63717
|
+
let matched = false;
|
|
63718
|
+
if (ref.packageId) {
|
|
63719
|
+
const w = byPackageId.get(ref.packageId);
|
|
63720
|
+
if (w) {
|
|
63721
|
+
applyRegistryMatch(w, name, resolved);
|
|
63722
|
+
matched = true;
|
|
63644
63723
|
}
|
|
63645
63724
|
}
|
|
63646
63725
|
|
|
63726
|
+
// Fallback path: no packageId on the layout item (legacy data).
|
|
63727
|
+
// Rank candidates by how much of this dashboard they cover so
|
|
63728
|
+
// shared-component bundles beat stray singleton packages.
|
|
63729
|
+
if (!matched) {
|
|
63730
|
+
const candidates = byComponentName.get(name);
|
|
63731
|
+
if (Array.isArray(candidates) && candidates.length > 0) {
|
|
63732
|
+
const ranked = rankCandidates(candidates);
|
|
63733
|
+
applyRegistryMatch(ranked[0], name, resolved);
|
|
63734
|
+
}
|
|
63735
|
+
}
|
|
63736
|
+
scope = resolved.scope;
|
|
63737
|
+
packageName = resolved.packageName;
|
|
63738
|
+
version = resolved.version;
|
|
63739
|
+
author = resolved.author;
|
|
63740
|
+
|
|
63647
63741
|
// Fallback: resolve from component configs (built-in widgets)
|
|
63648
63742
|
if (componentConfigs && componentConfigs[name]) {
|
|
63649
63743
|
const config = componentConfigs[name];
|
|
@@ -64244,6 +64338,68 @@ function collectComponentNamesFromWorkspace$1(workspace) {
|
|
|
64244
64338
|
return Array.from(names);
|
|
64245
64339
|
}
|
|
64246
64340
|
|
|
64341
|
+
/**
|
|
64342
|
+
* Walk the workspace and return one dependency ref per unique
|
|
64343
|
+
* (component, packageId) pair. `packageId` is the exact source
|
|
64344
|
+
* package id (e.g. `"@ai-built/pipeline"`) that was recorded on the
|
|
64345
|
+
* layout item when the widget was added. Items that predate the
|
|
64346
|
+
* packageId field carry `packageId: null`, and the caller falls back
|
|
64347
|
+
* to registry-based resolution for those.
|
|
64348
|
+
*
|
|
64349
|
+
* Unlike `collectComponentNamesFromWorkspace`, this walk is the
|
|
64350
|
+
* authoritative source for publish-time attribution — the publish
|
|
64351
|
+
* flow no longer needs to guess which installed package provides a
|
|
64352
|
+
* shared component when the layout item already says so.
|
|
64353
|
+
*
|
|
64354
|
+
* @param {Object} workspace - Workspace (layout/pages/sidebarLayout)
|
|
64355
|
+
* @returns {Array<{component: string, packageId: string|null}>}
|
|
64356
|
+
*/
|
|
64357
|
+
function collectDependencyRefsFromWorkspace$1(workspace) {
|
|
64358
|
+
const byKey = new Map();
|
|
64359
|
+
const walk = (items) => {
|
|
64360
|
+
if (!Array.isArray(items)) return;
|
|
64361
|
+
for (const item of items) {
|
|
64362
|
+
if (!item || typeof item !== "object") continue;
|
|
64363
|
+
const component = item.component;
|
|
64364
|
+
if (
|
|
64365
|
+
component &&
|
|
64366
|
+
component !== "Container" &&
|
|
64367
|
+
component !== "LayoutGridContainer"
|
|
64368
|
+
) {
|
|
64369
|
+
const packageId = item.packageId || null;
|
|
64370
|
+
const key = `${component}|${packageId || ""}`;
|
|
64371
|
+
if (!byKey.has(key)) byKey.set(key, { component, packageId });
|
|
64372
|
+
}
|
|
64373
|
+
// Grid cells may carry a string component name (new widget
|
|
64374
|
+
// placed directly in a cell) with no corresponding layout item
|
|
64375
|
+
// yet — capture it without a packageId so the fallback path
|
|
64376
|
+
// still picks it up.
|
|
64377
|
+
if (item.grid && typeof item.grid === "object") {
|
|
64378
|
+
for (const [cellKey, cell] of Object.entries(item.grid)) {
|
|
64379
|
+
if (!/^\d+\.\d+$/.test(cellKey)) continue;
|
|
64380
|
+
if (cell && typeof cell.component === "string") {
|
|
64381
|
+
const cellKey2 = `${cell.component}|`;
|
|
64382
|
+
if (!byKey.has(cellKey2)) {
|
|
64383
|
+
byKey.set(cellKey2, {
|
|
64384
|
+
component: cell.component,
|
|
64385
|
+
packageId: null,
|
|
64386
|
+
});
|
|
64387
|
+
}
|
|
64388
|
+
}
|
|
64389
|
+
}
|
|
64390
|
+
}
|
|
64391
|
+
if (Array.isArray(item.items)) walk(item.items);
|
|
64392
|
+
if (Array.isArray(item.layout)) walk(item.layout);
|
|
64393
|
+
}
|
|
64394
|
+
};
|
|
64395
|
+
walk(workspace?.layout);
|
|
64396
|
+
walk(workspace?.sidebarLayout);
|
|
64397
|
+
if (Array.isArray(workspace?.pages)) {
|
|
64398
|
+
for (const page of workspace.pages) walk(page?.layout);
|
|
64399
|
+
}
|
|
64400
|
+
return Array.from(byKey.values());
|
|
64401
|
+
}
|
|
64402
|
+
|
|
64247
64403
|
/**
|
|
64248
64404
|
* Extract event wiring across a workspace's main layout, every page
|
|
64249
64405
|
* layout, and the sidebar layout. Mirrors collectComponentNamesFromWorkspace
|
|
@@ -64333,6 +64489,7 @@ function stripPersonalizationFromWorkspace$1(workspace) {
|
|
|
64333
64489
|
var dashboardConfigUtils$1 = {
|
|
64334
64490
|
collectComponentNames: collectComponentNames$1,
|
|
64335
64491
|
collectComponentNamesFromWorkspace: collectComponentNamesFromWorkspace$1,
|
|
64492
|
+
collectDependencyRefsFromWorkspace: collectDependencyRefsFromWorkspace$1,
|
|
64336
64493
|
extractEventWiring: extractEventWiring$1,
|
|
64337
64494
|
extractEventWiringFromWorkspace: extractEventWiringFromWorkspace$1,
|
|
64338
64495
|
buildWidgetDependencies: buildWidgetDependencies$1,
|
|
@@ -65373,6 +65530,7 @@ const {
|
|
|
65373
65530
|
const {
|
|
65374
65531
|
collectComponentNames,
|
|
65375
65532
|
collectComponentNamesFromWorkspace,
|
|
65533
|
+
collectDependencyRefsFromWorkspace,
|
|
65376
65534
|
extractEventWiring,
|
|
65377
65535
|
extractEventWiringFromWorkspace,
|
|
65378
65536
|
buildWidgetDependencies,
|
|
@@ -66486,12 +66644,14 @@ async function collectDashboardDependencies$1(
|
|
|
66486
66644
|
};
|
|
66487
66645
|
}
|
|
66488
66646
|
|
|
66489
|
-
// 2. Collect
|
|
66490
|
-
|
|
66647
|
+
// 2. Collect dependency refs — each carries the exact packageId
|
|
66648
|
+
// recorded on the layout item when the widget was added, so
|
|
66649
|
+
// publish attribution is authoritative instead of heuristic.
|
|
66650
|
+
const refs = collectDependencyRefsFromWorkspace(workspace);
|
|
66491
66651
|
|
|
66492
66652
|
// 3. Resolve widget refs (scope, packageName, widgetName, version)
|
|
66493
66653
|
const deps = buildWidgetDependencies(
|
|
66494
|
-
|
|
66654
|
+
refs,
|
|
66495
66655
|
widgetRegistry,
|
|
66496
66656
|
options.componentConfigs || null,
|
|
66497
66657
|
);
|