@trops/dash-core 0.1.415 → 0.1.417
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 +559 -139
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +75 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +75 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -63840,7 +63840,13 @@ function generateRegistryManifest(dashboardConfig, options = {}) {
|
|
|
63840
63840
|
.toLowerCase();
|
|
63841
63841
|
|
|
63842
63842
|
const githubUser = options.githubUser || "";
|
|
63843
|
-
|
|
63843
|
+
// Prefer an explicitly-passed version (caller resolved it already,
|
|
63844
|
+
// e.g. via resolveNextVersion + bump). Fall back to the dashboard's
|
|
63845
|
+
// own version, then a 1.0.0 baseline. The previous hardcoded
|
|
63846
|
+
// "1.0.0" meant every republish looked identical to the registry;
|
|
63847
|
+
// latestVersion never advanced, so downstream update-check never
|
|
63848
|
+
// saw a diff and no notification fired.
|
|
63849
|
+
const version = options.version || dashboardConfig.version || "1.0.0";
|
|
63844
63850
|
const visibility = options.visibility === "private" ? "private" : "public";
|
|
63845
63851
|
|
|
63846
63852
|
const manifest = {
|
|
@@ -63867,13 +63873,31 @@ function generateRegistryManifest(dashboardConfig, options = {}) {
|
|
|
63867
63873
|
options.callerScope && w.scope && w.scope !== options.callerScope
|
|
63868
63874
|
? options.callerScope
|
|
63869
63875
|
: w.scope || "";
|
|
63876
|
+
// Packaged id — the scoped "@<scope>/<packageName>" string that
|
|
63877
|
+
// the install flow looks up in the registry. Build this from the
|
|
63878
|
+
// REMAPPED scope + bare packageName so installers resolve against
|
|
63879
|
+
// the scope the widget was actually published as, not the local
|
|
63880
|
+
// `@ai-built` convention. Stripping the scope prefix from a
|
|
63881
|
+
// potentially-scoped packageName keeps the result canonical.
|
|
63882
|
+
const bareName = stripScopePrefix(
|
|
63883
|
+
w.packageName || w.package || "",
|
|
63884
|
+
remappedScope || w.scope,
|
|
63885
|
+
);
|
|
63886
|
+
const scopedPackageId = remappedScope
|
|
63887
|
+
? `@${remappedScope.replace(/^@/, "")}/${bareName}`
|
|
63888
|
+
: bareName;
|
|
63870
63889
|
return {
|
|
63871
63890
|
id: w.id,
|
|
63872
63891
|
scope: remappedScope,
|
|
63873
|
-
packageName:
|
|
63892
|
+
packageName: bareName,
|
|
63874
63893
|
widgetName: w.widgetName || (w.id ? w.id.split(".").pop() : w.package),
|
|
63875
63894
|
name: w.id ? w.id.split(".").pop() : w.package,
|
|
63876
|
-
package
|
|
63895
|
+
// `package` is consumed by the install flow as the registry
|
|
63896
|
+
// package id (see installDashboardFromRegistry in
|
|
63897
|
+
// dashboardConfigController.js). Must carry the remapped
|
|
63898
|
+
// scope, otherwise installers look up an @ai-built/... id that
|
|
63899
|
+
// only exists on the publisher's machine.
|
|
63900
|
+
package: scopedPackageId,
|
|
63877
63901
|
version: w.version || "*",
|
|
63878
63902
|
required: w.required !== false,
|
|
63879
63903
|
author: w.author || "",
|
|
@@ -63982,11 +64006,27 @@ function buildDashboardPreview(source) {
|
|
|
63982
64006
|
* @returns {Array} Update records with workspace info and version comparison
|
|
63983
64007
|
*/
|
|
63984
64008
|
function checkDashboardUpdates(workspaces = [], registryPackages = []) {
|
|
63985
|
-
|
|
64009
|
+
// Index the registry by canonical `@scope/name` so the lookup
|
|
64010
|
+
// survives installs that capture scope differently from the
|
|
64011
|
+
// registry's raw `name` field. The previous map was keyed by bare
|
|
64012
|
+
// `pkg.name`, which misses anytime the installed config recorded
|
|
64013
|
+
// `@scope/name` (our new publish flow writes that) or when two
|
|
64014
|
+
// users publish the same bare name. Key both forms for safety.
|
|
64015
|
+
const registryByKey = new Map();
|
|
64016
|
+
const asKey = (scope, name) => {
|
|
64017
|
+
if (!name) return null;
|
|
64018
|
+
if (!scope) return name;
|
|
64019
|
+
const bareScope = String(scope).replace(/^@/, "");
|
|
64020
|
+
return `@${bareScope}/${name}`;
|
|
64021
|
+
};
|
|
63986
64022
|
for (const pkg of registryPackages) {
|
|
63987
|
-
if (pkg.name
|
|
63988
|
-
|
|
63989
|
-
|
|
64023
|
+
if (!pkg.name) continue;
|
|
64024
|
+
if ((pkg.type || "widget") !== "dashboard") continue;
|
|
64025
|
+
const scoped = asKey(pkg.scope, pkg.name);
|
|
64026
|
+
if (scoped) registryByKey.set(scoped, pkg);
|
|
64027
|
+
// Back-compat: also store under bare name so installed configs
|
|
64028
|
+
// that predate the scope-aware write continue to match.
|
|
64029
|
+
registryByKey.set(pkg.name, pkg);
|
|
63990
64030
|
}
|
|
63991
64031
|
|
|
63992
64032
|
const updates = [];
|
|
@@ -63995,7 +64035,24 @@ function checkDashboardUpdates(workspaces = [], registryPackages = []) {
|
|
|
63995
64035
|
const config = ws._dashboardConfig;
|
|
63996
64036
|
if (!config || !config.registryPackage) continue;
|
|
63997
64037
|
|
|
63998
|
-
|
|
64038
|
+
// Lookup chain: try the scoped form first, fall back to bare. The
|
|
64039
|
+
// installed config may record either. Scope is stored on the
|
|
64040
|
+
// config by the install flow (or set here by the publish persist
|
|
64041
|
+
// step we just added).
|
|
64042
|
+
const installedScope =
|
|
64043
|
+
config.registryScope ||
|
|
64044
|
+
(config.registryPackage.startsWith("@")
|
|
64045
|
+
? config.registryPackage.slice(1).split("/")[0]
|
|
64046
|
+
: null);
|
|
64047
|
+
const installedName = config.registryPackage.includes("/")
|
|
64048
|
+
? config.registryPackage.split("/").pop()
|
|
64049
|
+
: config.registryPackage;
|
|
64050
|
+
const scopedKey = asKey(installedScope, installedName);
|
|
64051
|
+
|
|
64052
|
+
const registryPkg =
|
|
64053
|
+
(scopedKey && registryByKey.get(scopedKey)) ||
|
|
64054
|
+
registryByKey.get(config.registryPackage) ||
|
|
64055
|
+
registryByKey.get(installedName);
|
|
63999
64056
|
if (!registryPkg) continue;
|
|
64000
64057
|
|
|
64001
64058
|
const installedVersion = config.installedVersion || "0.0.0";
|
|
@@ -64006,6 +64063,7 @@ function checkDashboardUpdates(workspaces = [], registryPackages = []) {
|
|
|
64006
64063
|
workspaceId: ws.id,
|
|
64007
64064
|
workspaceName: ws.name || ws.label || "",
|
|
64008
64065
|
registryPackage: config.registryPackage,
|
|
64066
|
+
registryScope: installedScope,
|
|
64009
64067
|
installedVersion,
|
|
64010
64068
|
latestVersion,
|
|
64011
64069
|
importedAt: config.importedAt || null,
|
|
@@ -64151,6 +64209,67 @@ function extractEventWiringFromWorkspace$1(workspace) {
|
|
|
64151
64209
|
return wiring;
|
|
64152
64210
|
}
|
|
64153
64211
|
|
|
64212
|
+
/**
|
|
64213
|
+
* Strip publisher-specific personalization (userPrefs + selectedProviders)
|
|
64214
|
+
* from every widget instance in a layout-ish structure. Used by the
|
|
64215
|
+
* dashboard publish flow so the installer starts with the widget's
|
|
64216
|
+
* own defaultValue on every field instead of inheriting the
|
|
64217
|
+
* publisher's absolute paths, region tags, credentials, etc.
|
|
64218
|
+
*
|
|
64219
|
+
* Walks the standard layout shapes that forEachWidget handles:
|
|
64220
|
+
* - top-level `layout` arrays
|
|
64221
|
+
* - `workspace.pages[*].layout`
|
|
64222
|
+
* - `workspace.sidebarLayout`
|
|
64223
|
+
* - `LayoutGridContainer` children stored on `item.items` / `item.layout`
|
|
64224
|
+
*
|
|
64225
|
+
* Returns a deep copy — never mutates the input workspace.
|
|
64226
|
+
*
|
|
64227
|
+
* Title-ish defaults (widget.name) are intentionally preserved — they
|
|
64228
|
+
* are part of the dashboard template, not personal data. Anything else
|
|
64229
|
+
* under userPrefs is dropped; the installer's widget re-reads the
|
|
64230
|
+
* `defaultValue` declared in the component's `.dash.js`.
|
|
64231
|
+
*/
|
|
64232
|
+
function stripPersonalizationFromWorkspace$1(workspace) {
|
|
64233
|
+
if (!workspace) return workspace;
|
|
64234
|
+
const cleanItem = (item) => {
|
|
64235
|
+
if (!item || typeof item !== "object") return item;
|
|
64236
|
+
// Preserve the layout position + children, but blank out the
|
|
64237
|
+
// user-set config values that are tied to the publisher's machine.
|
|
64238
|
+
const cleaned = { ...item };
|
|
64239
|
+
if ("userPrefs" in cleaned) delete cleaned.userPrefs;
|
|
64240
|
+
if ("selectedProviders" in cleaned) delete cleaned.selectedProviders;
|
|
64241
|
+
if (Array.isArray(cleaned.items)) {
|
|
64242
|
+
cleaned.items = cleaned.items.map(cleanItem);
|
|
64243
|
+
}
|
|
64244
|
+
if (Array.isArray(cleaned.layout)) {
|
|
64245
|
+
cleaned.layout = cleaned.layout.map(cleanItem);
|
|
64246
|
+
}
|
|
64247
|
+
return cleaned;
|
|
64248
|
+
};
|
|
64249
|
+
const cleaned = { ...workspace };
|
|
64250
|
+
if (Array.isArray(cleaned.layout))
|
|
64251
|
+
cleaned.layout = cleaned.layout.map(cleanItem);
|
|
64252
|
+
if (Array.isArray(cleaned.sidebarLayout))
|
|
64253
|
+
cleaned.sidebarLayout = cleaned.sidebarLayout.map(cleanItem);
|
|
64254
|
+
if (Array.isArray(cleaned.pages)) {
|
|
64255
|
+
cleaned.pages = cleaned.pages.map((page) =>
|
|
64256
|
+
page
|
|
64257
|
+
? {
|
|
64258
|
+
...page,
|
|
64259
|
+
...(Array.isArray(page.layout)
|
|
64260
|
+
? { layout: page.layout.map(cleanItem) }
|
|
64261
|
+
: {}),
|
|
64262
|
+
}
|
|
64263
|
+
: page,
|
|
64264
|
+
);
|
|
64265
|
+
}
|
|
64266
|
+
// Workspace-level selectedProviders map lives at the top level for
|
|
64267
|
+
// some older workspaces; drop it too so the installer doesn't get
|
|
64268
|
+
// bindings to provider names that don't exist on their machine.
|
|
64269
|
+
if ("selectedProviders" in cleaned) delete cleaned.selectedProviders;
|
|
64270
|
+
return cleaned;
|
|
64271
|
+
}
|
|
64272
|
+
|
|
64154
64273
|
var dashboardConfigUtils$1 = {
|
|
64155
64274
|
collectComponentNames: collectComponentNames$1,
|
|
64156
64275
|
collectComponentNamesFromWorkspace: collectComponentNamesFromWorkspace$1,
|
|
@@ -64165,6 +64284,7 @@ var dashboardConfigUtils$1 = {
|
|
|
64165
64284
|
checkDashboardUpdates,
|
|
64166
64285
|
buildProviderSetupManifest,
|
|
64167
64286
|
checkApiCompatibility,
|
|
64287
|
+
stripPersonalizationFromWorkspace: stripPersonalizationFromWorkspace$1,
|
|
64168
64288
|
};
|
|
64169
64289
|
|
|
64170
64290
|
/**
|
|
@@ -64315,6 +64435,128 @@ var registryApiController$3 = {
|
|
|
64315
64435
|
REGISTRY_BASE_URL,
|
|
64316
64436
|
};
|
|
64317
64437
|
|
|
64438
|
+
/**
|
|
64439
|
+
* widgetPublishManifest.js
|
|
64440
|
+
*
|
|
64441
|
+
* Pure helpers for widget-publish flow — version bumping, package-name
|
|
64442
|
+
* parsing, and manifest generation. No electron / fs / adm-zip deps so
|
|
64443
|
+
* these can be unit-tested directly.
|
|
64444
|
+
*/
|
|
64445
|
+
|
|
64446
|
+
var widgetPublishManifest;
|
|
64447
|
+
var hasRequiredWidgetPublishManifest;
|
|
64448
|
+
|
|
64449
|
+
function requireWidgetPublishManifest () {
|
|
64450
|
+
if (hasRequiredWidgetPublishManifest) return widgetPublishManifest;
|
|
64451
|
+
hasRequiredWidgetPublishManifest = 1;
|
|
64452
|
+
const SEMVER_RE =
|
|
64453
|
+
/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
64454
|
+
|
|
64455
|
+
function bumpVersion(current, type) {
|
|
64456
|
+
if (!current || typeof current !== "string") return "1.0.0";
|
|
64457
|
+
const match = current.match(SEMVER_RE);
|
|
64458
|
+
if (!match) return current;
|
|
64459
|
+
let [, major, minor, patch] = match;
|
|
64460
|
+
major = Number(major);
|
|
64461
|
+
minor = Number(minor);
|
|
64462
|
+
patch = Number(patch);
|
|
64463
|
+
switch (type) {
|
|
64464
|
+
case "major":
|
|
64465
|
+
return `${major + 1}.0.0`;
|
|
64466
|
+
case "minor":
|
|
64467
|
+
return `${major}.${minor + 1}.0`;
|
|
64468
|
+
case "patch":
|
|
64469
|
+
default:
|
|
64470
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
64471
|
+
}
|
|
64472
|
+
}
|
|
64473
|
+
|
|
64474
|
+
function resolveNextVersion(currentVersion, options = {}) {
|
|
64475
|
+
if (options.version) return options.version;
|
|
64476
|
+
if (options.bump) return bumpVersion(currentVersion, options.bump);
|
|
64477
|
+
return currentVersion;
|
|
64478
|
+
}
|
|
64479
|
+
|
|
64480
|
+
function parsePackageName(pkgName) {
|
|
64481
|
+
if (!pkgName) return { scope: null, name: "" };
|
|
64482
|
+
const m = pkgName.match(/^@([^/]+)\/(.+)$/);
|
|
64483
|
+
if (m) return { scope: m[1], name: m[2] };
|
|
64484
|
+
return { scope: null, name: pkgName };
|
|
64485
|
+
}
|
|
64486
|
+
|
|
64487
|
+
function generateWidgetRegistryManifest(
|
|
64488
|
+
packageJson,
|
|
64489
|
+
widgetConfigs,
|
|
64490
|
+
options = {},
|
|
64491
|
+
) {
|
|
64492
|
+
const parsed = parsePackageName(packageJson.name || "");
|
|
64493
|
+
const scope = options.scope || parsed.scope || "";
|
|
64494
|
+
const name = options.name || parsed.name || packageJson.name || "";
|
|
64495
|
+
const version = options.version || packageJson.version || "1.0.0";
|
|
64496
|
+
const visibility = options.visibility === "private" ? "private" : "public";
|
|
64497
|
+
|
|
64498
|
+
const providerKeys = new Set();
|
|
64499
|
+
const providers = [];
|
|
64500
|
+
for (const cfg of widgetConfigs || []) {
|
|
64501
|
+
if (!Array.isArray(cfg.providers)) continue;
|
|
64502
|
+
for (const p of cfg.providers) {
|
|
64503
|
+
const key = `${p.type}:${p.providerClass || "mcp"}`;
|
|
64504
|
+
if (providerKeys.has(key)) continue;
|
|
64505
|
+
providerKeys.add(key);
|
|
64506
|
+
providers.push({
|
|
64507
|
+
type: p.type,
|
|
64508
|
+
required: p.required !== false,
|
|
64509
|
+
providerClass: p.providerClass || "mcp",
|
|
64510
|
+
});
|
|
64511
|
+
}
|
|
64512
|
+
}
|
|
64513
|
+
|
|
64514
|
+
const widgets = (widgetConfigs || []).map((cfg) => ({
|
|
64515
|
+
name: cfg.component || cfg.name,
|
|
64516
|
+
displayName: cfg.name || cfg.component,
|
|
64517
|
+
description: cfg.description || "",
|
|
64518
|
+
icon: cfg.icon || "square",
|
|
64519
|
+
providers: Array.isArray(cfg.providers)
|
|
64520
|
+
? cfg.providers.map((p) => ({
|
|
64521
|
+
type: p.type,
|
|
64522
|
+
required: p.required !== false,
|
|
64523
|
+
providerClass: p.providerClass || "mcp",
|
|
64524
|
+
}))
|
|
64525
|
+
: [],
|
|
64526
|
+
}));
|
|
64527
|
+
|
|
64528
|
+
return {
|
|
64529
|
+
scope,
|
|
64530
|
+
name,
|
|
64531
|
+
displayName: options.displayName || packageJson.displayName || name,
|
|
64532
|
+
version,
|
|
64533
|
+
type: "widget",
|
|
64534
|
+
visibility,
|
|
64535
|
+
description: options.description || packageJson.description || "",
|
|
64536
|
+
author:
|
|
64537
|
+
options.authorName ||
|
|
64538
|
+
(typeof packageJson.author === "string"
|
|
64539
|
+
? packageJson.author
|
|
64540
|
+
: packageJson.author?.name || ""),
|
|
64541
|
+
category: options.category || "general",
|
|
64542
|
+
tags: Array.isArray(options.tags) ? options.tags : [],
|
|
64543
|
+
icon: options.icon || "puzzle-piece",
|
|
64544
|
+
providers,
|
|
64545
|
+
widgets,
|
|
64546
|
+
appOrigin: options.appOrigin || "",
|
|
64547
|
+
publishedAt: new Date().toISOString(),
|
|
64548
|
+
};
|
|
64549
|
+
}
|
|
64550
|
+
|
|
64551
|
+
widgetPublishManifest = {
|
|
64552
|
+
bumpVersion,
|
|
64553
|
+
resolveNextVersion,
|
|
64554
|
+
parsePackageName,
|
|
64555
|
+
generateWidgetRegistryManifest,
|
|
64556
|
+
};
|
|
64557
|
+
return widgetPublishManifest;
|
|
64558
|
+
}
|
|
64559
|
+
|
|
64318
64560
|
/**
|
|
64319
64561
|
* themeRegistryController.js
|
|
64320
64562
|
*
|
|
@@ -64359,14 +64601,20 @@ function generateThemeRegistryManifest(themeData, themeKey, options = {}) {
|
|
|
64359
64601
|
const sanitizedName = sanitizeName(humanName);
|
|
64360
64602
|
const colors = extractColors(themeData);
|
|
64361
64603
|
const visibility = options.visibility === "private" ? "private" : "public";
|
|
64604
|
+
// Prefer an explicitly-resolved version (caller already bumped),
|
|
64605
|
+
// then the theme's own stored version, then the 1.0.0 baseline.
|
|
64606
|
+
// The old hardcoded 1.0.0 meant republishes silently clobbered the
|
|
64607
|
+
// registry record — update notifications never fired downstream.
|
|
64608
|
+
const version = options.version || themeData.version || "1.0.0";
|
|
64362
64609
|
|
|
64363
64610
|
return {
|
|
64364
64611
|
scope: options.scope || "",
|
|
64365
64612
|
name: sanitizedName,
|
|
64366
64613
|
displayName: humanName,
|
|
64367
|
-
author:
|
|
64614
|
+
author:
|
|
64615
|
+
options.authorName || themeData.author || options.fallbackAuthor || "",
|
|
64368
64616
|
description: options.description || "",
|
|
64369
|
-
version
|
|
64617
|
+
version,
|
|
64370
64618
|
visibility,
|
|
64371
64619
|
type: "theme",
|
|
64372
64620
|
category: "general",
|
|
@@ -64436,6 +64684,7 @@ function extractColors(themeData) {
|
|
|
64436
64684
|
*/
|
|
64437
64685
|
async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
|
|
64438
64686
|
try {
|
|
64687
|
+
const { resolveNextVersion } = requireWidgetPublishManifest();
|
|
64439
64688
|
// Read the theme data
|
|
64440
64689
|
const themesResult = themeController$3.listThemesForApplication(win, appId);
|
|
64441
64690
|
if (themesResult.error) {
|
|
@@ -64469,11 +64718,33 @@ async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
|
|
|
64469
64718
|
};
|
|
64470
64719
|
}
|
|
64471
64720
|
|
|
64721
|
+
// Resolve version: prefer explicit, then bump the theme's stored
|
|
64722
|
+
// version, then start at 1.0.0. Without this themes always
|
|
64723
|
+
// published as 1.0.0 and update-check could never diff.
|
|
64724
|
+
const previousVersion = themeData.version || "1.0.0";
|
|
64725
|
+
const nextVersion = resolveNextVersion(previousVersion, {
|
|
64726
|
+
bump: options.bump,
|
|
64727
|
+
version: options.version,
|
|
64728
|
+
});
|
|
64729
|
+
|
|
64730
|
+
// Author fallback chain (F7): explicit → theme data → registry
|
|
64731
|
+
// profile displayName/username → blank. Matches the widget
|
|
64732
|
+
// author-normalization shape so ai-built / scaffolded themes
|
|
64733
|
+
// don't ship to the registry with a blank author field.
|
|
64734
|
+
const resolvedAuthor =
|
|
64735
|
+
options.authorName ||
|
|
64736
|
+
themeData.author ||
|
|
64737
|
+
profile?.displayName ||
|
|
64738
|
+
profile?.username ||
|
|
64739
|
+
"";
|
|
64740
|
+
|
|
64472
64741
|
// Generate manifest
|
|
64473
64742
|
const manifest = generateThemeRegistryManifest(themeData, themeKey, {
|
|
64474
64743
|
...options,
|
|
64475
64744
|
scope,
|
|
64476
64745
|
appOrigin: appId,
|
|
64746
|
+
version: nextVersion,
|
|
64747
|
+
authorName: resolvedAuthor,
|
|
64477
64748
|
});
|
|
64478
64749
|
|
|
64479
64750
|
// Validate colors
|
|
@@ -64530,6 +64801,35 @@ async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
|
|
|
64530
64801
|
"[ThemeRegistryController] Registry publish result:",
|
|
64531
64802
|
registryResult,
|
|
64532
64803
|
);
|
|
64804
|
+
// Persist the resolved version + author back onto the theme so
|
|
64805
|
+
// the NEXT publish picks up from here. Without this, the
|
|
64806
|
+
// publisher would be bumping from 1.0.0 every time and the
|
|
64807
|
+
// manifest's author normalization would be re-applied every
|
|
64808
|
+
// run (OK but confusing).
|
|
64809
|
+
if (registryResult?.success) {
|
|
64810
|
+
try {
|
|
64811
|
+
const updatedTheme = {
|
|
64812
|
+
...themeData,
|
|
64813
|
+
version: nextVersion,
|
|
64814
|
+
author: resolvedAuthor || themeData.author,
|
|
64815
|
+
_registryMeta: {
|
|
64816
|
+
...(themeData._registryMeta || {}),
|
|
64817
|
+
packageName: `${scope}/${manifest.name}`,
|
|
64818
|
+
scope,
|
|
64819
|
+
lastPublishedAt: new Date().toISOString(),
|
|
64820
|
+
lastPublishedVersion: nextVersion,
|
|
64821
|
+
},
|
|
64822
|
+
};
|
|
64823
|
+
themeController$3.saveThemeForApplication(win, appId, {
|
|
64824
|
+
key: themeKey,
|
|
64825
|
+
theme: updatedTheme,
|
|
64826
|
+
});
|
|
64827
|
+
} catch (persistErr) {
|
|
64828
|
+
console.warn(
|
|
64829
|
+
`[ThemeRegistryController] Version persist failed (continuing): ${persistErr.message}`,
|
|
64830
|
+
);
|
|
64831
|
+
}
|
|
64832
|
+
}
|
|
64533
64833
|
}
|
|
64534
64834
|
|
|
64535
64835
|
return {
|
|
@@ -64870,12 +65170,120 @@ function getThemePublishPreview$1(appId, themeKey) {
|
|
|
64870
65170
|
}
|
|
64871
65171
|
}
|
|
64872
65172
|
|
|
65173
|
+
/**
|
|
65174
|
+
* Check installed themes for available updates against the registry.
|
|
65175
|
+
*
|
|
65176
|
+
* Reads every theme from the app's theme file, picks the ones that
|
|
65177
|
+
* carry a `_registryMeta.packageName` (i.e. were installed from the
|
|
65178
|
+
* registry, not locally created), resolves each against the registry
|
|
65179
|
+
* index by `@scope/name` (with a bare-name fallback), and returns a
|
|
65180
|
+
* diff record for each stale theme.
|
|
65181
|
+
*
|
|
65182
|
+
* Mirrors `checkDashboardUpdatesForApp` — callable standalone, works
|
|
65183
|
+
* the same way on the renderer side.
|
|
65184
|
+
*
|
|
65185
|
+
* @param {BrowserWindow} win
|
|
65186
|
+
* @param {string} appId
|
|
65187
|
+
* @returns {Promise<{success, updates, totalInstalled, error?}>}
|
|
65188
|
+
*/
|
|
65189
|
+
async function checkThemeUpdatesForApp$1(win, appId) {
|
|
65190
|
+
try {
|
|
65191
|
+
const { fetchRegistryIndex } = registryController$3;
|
|
65192
|
+
const themesResult = themeController$3.listThemesForApplication(win, appId);
|
|
65193
|
+
if (themesResult.error) {
|
|
65194
|
+
return {
|
|
65195
|
+
success: false,
|
|
65196
|
+
error: themesResult.message || "Failed to read themes",
|
|
65197
|
+
updates: [],
|
|
65198
|
+
};
|
|
65199
|
+
}
|
|
65200
|
+
const themes = themesResult.themes || {};
|
|
65201
|
+
|
|
65202
|
+
// Filter to registry-installed themes only.
|
|
65203
|
+
const installed = [];
|
|
65204
|
+
for (const [themeKey, themeData] of Object.entries(themes)) {
|
|
65205
|
+
const meta = themeData?._registryMeta;
|
|
65206
|
+
if (!meta?.packageName) continue;
|
|
65207
|
+
installed.push({
|
|
65208
|
+
themeKey,
|
|
65209
|
+
packageName: meta.packageName,
|
|
65210
|
+
scope: meta.scope || null,
|
|
65211
|
+
version: themeData.version || meta.lastPublishedVersion || "0.0.0",
|
|
65212
|
+
});
|
|
65213
|
+
}
|
|
65214
|
+
|
|
65215
|
+
if (installed.length === 0) {
|
|
65216
|
+
return { success: true, updates: [], totalInstalled: 0 };
|
|
65217
|
+
}
|
|
65218
|
+
|
|
65219
|
+
const index = await fetchRegistryIndex();
|
|
65220
|
+
const packages = (index.packages || []).filter(
|
|
65221
|
+
(p) => (p.type || "widget") === "theme",
|
|
65222
|
+
);
|
|
65223
|
+
|
|
65224
|
+
// Index registry packages by scoped + bare key, same pattern as
|
|
65225
|
+
// dashboard update check.
|
|
65226
|
+
const registryByKey = new Map();
|
|
65227
|
+
for (const pkg of packages) {
|
|
65228
|
+
if (!pkg.name) continue;
|
|
65229
|
+
if (pkg.scope) {
|
|
65230
|
+
const bareScope = String(pkg.scope).replace(/^@/, "");
|
|
65231
|
+
registryByKey.set(`@${bareScope}/${pkg.name}`, pkg);
|
|
65232
|
+
}
|
|
65233
|
+
registryByKey.set(pkg.name, pkg);
|
|
65234
|
+
}
|
|
65235
|
+
|
|
65236
|
+
const updates = [];
|
|
65237
|
+
for (const inst of installed) {
|
|
65238
|
+
const scope = inst.scope
|
|
65239
|
+
? String(inst.scope).replace(/^@/, "")
|
|
65240
|
+
: inst.packageName.startsWith("@")
|
|
65241
|
+
? inst.packageName.slice(1).split("/")[0]
|
|
65242
|
+
: null;
|
|
65243
|
+
const bareName = inst.packageName.includes("/")
|
|
65244
|
+
? inst.packageName.split("/").pop()
|
|
65245
|
+
: inst.packageName;
|
|
65246
|
+
const scopedKey = scope ? `@${scope}/${bareName}` : null;
|
|
65247
|
+
const registryPkg =
|
|
65248
|
+
(scopedKey && registryByKey.get(scopedKey)) ||
|
|
65249
|
+
registryByKey.get(inst.packageName) ||
|
|
65250
|
+
registryByKey.get(bareName);
|
|
65251
|
+
if (!registryPkg) continue;
|
|
65252
|
+
|
|
65253
|
+
const latestVersion = registryPkg.version || "0.0.0";
|
|
65254
|
+
if (inst.version !== latestVersion) {
|
|
65255
|
+
updates.push({
|
|
65256
|
+
themeKey: inst.themeKey,
|
|
65257
|
+
packageName: inst.packageName,
|
|
65258
|
+
scope,
|
|
65259
|
+
installedVersion: inst.version,
|
|
65260
|
+
latestVersion,
|
|
65261
|
+
downloadUrl: registryPkg.downloadUrl || null,
|
|
65262
|
+
});
|
|
65263
|
+
}
|
|
65264
|
+
}
|
|
65265
|
+
|
|
65266
|
+
return {
|
|
65267
|
+
success: true,
|
|
65268
|
+
updates,
|
|
65269
|
+
totalInstalled: installed.length,
|
|
65270
|
+
};
|
|
65271
|
+
} catch (err) {
|
|
65272
|
+
console.error(
|
|
65273
|
+
"[ThemeRegistryController] Error checking theme updates:",
|
|
65274
|
+
err,
|
|
65275
|
+
);
|
|
65276
|
+
return { success: false, error: err.message, updates: [] };
|
|
65277
|
+
}
|
|
65278
|
+
}
|
|
65279
|
+
|
|
64873
65280
|
var themeRegistryController$1 = {
|
|
64874
65281
|
prepareThemeForPublish: prepareThemeForPublish$1,
|
|
64875
65282
|
installThemeFromRegistry: installThemeFromRegistry$1,
|
|
64876
65283
|
getThemePublishPreview: getThemePublishPreview$1,
|
|
64877
65284
|
generateThemeRegistryManifest,
|
|
64878
65285
|
extractColors,
|
|
65286
|
+
checkThemeUpdatesForApp: checkThemeUpdatesForApp$1,
|
|
64879
65287
|
};
|
|
64880
65288
|
|
|
64881
65289
|
/**
|
|
@@ -64910,6 +65318,7 @@ const {
|
|
|
64910
65318
|
buildWidgetDependencies,
|
|
64911
65319
|
buildProviderRequirements,
|
|
64912
65320
|
applyEventWiringToLayout,
|
|
65321
|
+
stripPersonalizationFromWorkspace,
|
|
64913
65322
|
} = dashboardConfigUtils$1;
|
|
64914
65323
|
const { searchRegistry, getPackage } = registryController$3;
|
|
64915
65324
|
const { getStoredToken, clearToken } = registryAuthController$2;
|
|
@@ -64957,7 +65366,11 @@ async function exportDashboardConfig$1(
|
|
|
64957
65366
|
};
|
|
64958
65367
|
}
|
|
64959
65368
|
|
|
64960
|
-
|
|
65369
|
+
// Strip publisher-specific personalization (userPrefs,
|
|
65370
|
+
// selectedProviders) so the exported file carries a clean
|
|
65371
|
+
// template, not one pre-filled with the publisher's paths.
|
|
65372
|
+
const sharedWorkspace = stripPersonalizationFromWorkspace(workspace);
|
|
65373
|
+
const layout = sharedWorkspace.layout || [];
|
|
64961
65374
|
|
|
64962
65375
|
// 2. Collect components, extract wiring, resolve deps — walk main
|
|
64963
65376
|
// layout, every page, and the sidebar so multi-page / sidebar
|
|
@@ -64985,13 +65398,17 @@ async function exportDashboardConfig$1(
|
|
|
64985
65398
|
label: workspace.label || workspace.name,
|
|
64986
65399
|
version: workspace.version || 1,
|
|
64987
65400
|
layout,
|
|
64988
|
-
...(Array.isArray(
|
|
64989
|
-
|
|
65401
|
+
...(Array.isArray(sharedWorkspace.pages) &&
|
|
65402
|
+
sharedWorkspace.pages.length > 0
|
|
65403
|
+
? {
|
|
65404
|
+
pages: sharedWorkspace.pages,
|
|
65405
|
+
activePageId: workspace.activePageId,
|
|
65406
|
+
}
|
|
64990
65407
|
: {}),
|
|
64991
|
-
...(Array.isArray(
|
|
64992
|
-
|
|
65408
|
+
...(Array.isArray(sharedWorkspace.sidebarLayout) &&
|
|
65409
|
+
sharedWorkspace.sidebarLayout.length > 0
|
|
64993
65410
|
? {
|
|
64994
|
-
sidebarLayout:
|
|
65411
|
+
sidebarLayout: sharedWorkspace.sidebarLayout,
|
|
64995
65412
|
sidebarEnabled: workspace.sidebarEnabled !== false,
|
|
64996
65413
|
}
|
|
64997
65414
|
: {}),
|
|
@@ -65331,7 +65748,30 @@ async function processDashboardConfig(
|
|
|
65331
65748
|
dashboardConfig.widgets.length
|
|
65332
65749
|
) {
|
|
65333
65750
|
const installedWidgets = widgetRegistry.getWidgets();
|
|
65334
|
-
|
|
65751
|
+
// Build a canonical id set — `@scope/name` — so lookups survive
|
|
65752
|
+
// the publisher/installer having the widget under different
|
|
65753
|
+
// keys. The widget-registry entry carries `w.packageId`,
|
|
65754
|
+
// `w.name`, and `w.scope`; the dashboard dep carries
|
|
65755
|
+
// `dep.package` (now scope-remapped at publish time). Seeding
|
|
65756
|
+
// every form we've seen avoids silent "missing widget" misses
|
|
65757
|
+
// on bare-vs-scoped mismatch.
|
|
65758
|
+
const canonicalId = (w) => {
|
|
65759
|
+
if (w?.packageId) return w.packageId;
|
|
65760
|
+
if (w?.scope && w?.name) {
|
|
65761
|
+
const scope = String(w.scope).replace(/^@/, "");
|
|
65762
|
+
const bareName = String(w.name).replace(new RegExp(`^@?${scope}/`), "");
|
|
65763
|
+
return `@${scope}/${bareName}`;
|
|
65764
|
+
}
|
|
65765
|
+
return w?.name || null;
|
|
65766
|
+
};
|
|
65767
|
+
const installedPackages = new Set();
|
|
65768
|
+
for (const w of installedWidgets) {
|
|
65769
|
+
const id = canonicalId(w);
|
|
65770
|
+
if (id) installedPackages.add(id);
|
|
65771
|
+
// Back-compat: keep bare name in the set too, so older
|
|
65772
|
+
// dashboard configs (pre-scope-remap) still match.
|
|
65773
|
+
if (w?.name) installedPackages.add(w.name);
|
|
65774
|
+
}
|
|
65335
65775
|
|
|
65336
65776
|
// Emit initial "pending" state for all widgets
|
|
65337
65777
|
for (let i = 0; i < widgetTotal; i++) {
|
|
@@ -65369,7 +65809,20 @@ async function processDashboardConfig(
|
|
|
65369
65809
|
const displayName =
|
|
65370
65810
|
widgetDep.displayName || widgetDep.name || packageName;
|
|
65371
65811
|
|
|
65372
|
-
|
|
65812
|
+
// Try both the fully-scoped id and a bare-name fallback — the
|
|
65813
|
+
// installed set holds both forms, but the dashboard dep may
|
|
65814
|
+
// carry either shape. Without this, a widget stored locally as
|
|
65815
|
+
// `@trops/pipeline` and referenced as `pipeline` (or vice
|
|
65816
|
+
// versa) silently flagged as "failed" even though it was
|
|
65817
|
+
// installed.
|
|
65818
|
+
const isInstalled =
|
|
65819
|
+
installedPackages.has(packageName) ||
|
|
65820
|
+
(packageName?.includes("/") &&
|
|
65821
|
+
installedPackages.has(packageName.split("/").pop())) ||
|
|
65822
|
+
(packageName &&
|
|
65823
|
+
!packageName.startsWith("@") &&
|
|
65824
|
+
installedPackages.has(`@${packageName}`));
|
|
65825
|
+
if (isInstalled) {
|
|
65373
65826
|
installSummary.alreadyInstalled.push(packageName);
|
|
65374
65827
|
win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
|
|
65375
65828
|
packageName,
|
|
@@ -65401,6 +65854,10 @@ async function processDashboardConfig(
|
|
|
65401
65854
|
);
|
|
65402
65855
|
installSummary.installed.push({ packageName, config });
|
|
65403
65856
|
installedPackages.add(packageName);
|
|
65857
|
+
// Also add the canonical form so a subsequent dep that
|
|
65858
|
+
// references it under a different shape still hits.
|
|
65859
|
+
const installedCanonical = canonicalId(config);
|
|
65860
|
+
if (installedCanonical) installedPackages.add(installedCanonical);
|
|
65404
65861
|
win.webContents.send(DASHBOARD_CONFIG_INSTALL_PROGRESS, {
|
|
65405
65862
|
packageName,
|
|
65406
65863
|
displayName,
|
|
@@ -66138,16 +66595,30 @@ async function getDashboardPublishPlan$1(
|
|
|
66138
66595
|
}
|
|
66139
66596
|
}
|
|
66140
66597
|
|
|
66598
|
+
// Scopes that only exist on the publisher's machine and aren't
|
|
66599
|
+
// resolvable from the registry as-is. Any dep under one of these
|
|
66600
|
+
// scopes MUST be republished under the caller's scope for the
|
|
66601
|
+
// dashboard's widget refs to work on another machine. The modal
|
|
66602
|
+
// uses this flag to auto-check + lock such rows.
|
|
66603
|
+
const LOCAL_ONLY_SCOPES = new Set(["ai-built", "@ai-built"]);
|
|
66604
|
+
|
|
66141
66605
|
const widgets = deps.widgets.map((w) => {
|
|
66142
66606
|
const publishScope = publishScopeFor(w);
|
|
66143
66607
|
const key =
|
|
66144
66608
|
publishScope && w.packageName
|
|
66145
66609
|
? `${publishScope}/${w.packageName}`
|
|
66146
66610
|
: null;
|
|
66611
|
+
const isLocalOnlyScope =
|
|
66612
|
+
!!w.scope && LOCAL_ONLY_SCOPES.has(String(w.scope).replace(/^@/, ""));
|
|
66147
66613
|
return {
|
|
66148
66614
|
...w,
|
|
66149
66615
|
publishScope,
|
|
66150
66616
|
registry: key ? resolvedByKey.get(key) || null : null,
|
|
66617
|
+
// True when this widget cannot be installed as-is under its
|
|
66618
|
+
// local scope — the dashboard publish MUST republish it under
|
|
66619
|
+
// the caller's scope alongside the dashboard itself. The
|
|
66620
|
+
// modal treats this as mandatory rather than opt-in.
|
|
66621
|
+
requiresRepublish: isLocalOnlyScope,
|
|
66151
66622
|
};
|
|
66152
66623
|
});
|
|
66153
66624
|
|
|
@@ -66211,6 +66682,7 @@ async function prepareDashboardForPublish$1(
|
|
|
66211
66682
|
const {
|
|
66212
66683
|
generateRegistryManifest,
|
|
66213
66684
|
} = dashboardConfigUtils$1;
|
|
66685
|
+
const { resolveNextVersion } = requireWidgetPublishManifest();
|
|
66214
66686
|
|
|
66215
66687
|
// 1. Read workspace
|
|
66216
66688
|
const filename = path$2.join(
|
|
@@ -66243,7 +66715,29 @@ async function prepareDashboardForPublish$1(
|
|
|
66243
66715
|
};
|
|
66244
66716
|
}
|
|
66245
66717
|
|
|
66246
|
-
|
|
66718
|
+
// Resolve the version this publish will ship. Previous publishes
|
|
66719
|
+
// store the last version on workspace._dashboardConfig.version; new
|
|
66720
|
+
// dashboards start at 1.0.0. Caller may pass `options.version`
|
|
66721
|
+
// (explicit) or `options.bump` ("patch"/"minor"/"major"). Without
|
|
66722
|
+
// this, every dashboard republish used a hardcoded 1.0.0 — the
|
|
66723
|
+
// registry never saw a new version, so the update-check never
|
|
66724
|
+
// fired a notification for installers.
|
|
66725
|
+
const previousVersion = workspace._dashboardConfig?.version || "1.0.0";
|
|
66726
|
+
const nextVersion = resolveNextVersion(previousVersion, {
|
|
66727
|
+
bump: options.bump,
|
|
66728
|
+
version: options.version,
|
|
66729
|
+
});
|
|
66730
|
+
|
|
66731
|
+
// Strip publisher-specific personalization (userPrefs,
|
|
66732
|
+
// selectedProviders) from every widget instance before we snapshot
|
|
66733
|
+
// the workspace into the dashboardConfig. Without this, every
|
|
66734
|
+
// installer inherits the publisher's absolute filesystem paths,
|
|
66735
|
+
// region tags, and provider bindings as their "defaults" — a
|
|
66736
|
+
// widget's own `defaultValue` on each field never gets a chance.
|
|
66737
|
+
// Layout position, ordering, nested containers, and any title text
|
|
66738
|
+
// are preserved (they're part of the template, not personal).
|
|
66739
|
+
const sharedWorkspace = stripPersonalizationFromWorkspace(workspace);
|
|
66740
|
+
const layout = sharedWorkspace.layout || [];
|
|
66247
66741
|
|
|
66248
66742
|
// 3. Build the dashboard config — walk main + pages + sidebar
|
|
66249
66743
|
const componentNames = collectComponentNamesFromWorkspace(workspace);
|
|
@@ -66270,6 +66764,10 @@ async function prepareDashboardForPublish$1(
|
|
|
66270
66764
|
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
66271
66765
|
name: workspace.name || workspace.label || "Dashboard",
|
|
66272
66766
|
description: options.description || "",
|
|
66767
|
+
// Package version (semver). Distinct from workspace.version
|
|
66768
|
+
// (schema revision, integer). Persisted on the workspace after a
|
|
66769
|
+
// successful publish so the next publish resolves from here.
|
|
66770
|
+
version: nextVersion,
|
|
66273
66771
|
...(options.authorName
|
|
66274
66772
|
? { author: { name: options.authorName, id: options.authorId || "" } }
|
|
66275
66773
|
: {}),
|
|
@@ -66283,13 +66781,17 @@ async function prepareDashboardForPublish$1(
|
|
|
66283
66781
|
label: workspace.label || workspace.name,
|
|
66284
66782
|
version: workspace.version || 1,
|
|
66285
66783
|
layout,
|
|
66286
|
-
...(Array.isArray(
|
|
66287
|
-
|
|
66784
|
+
...(Array.isArray(sharedWorkspace.pages) &&
|
|
66785
|
+
sharedWorkspace.pages.length > 0
|
|
66786
|
+
? {
|
|
66787
|
+
pages: sharedWorkspace.pages,
|
|
66788
|
+
activePageId: workspace.activePageId,
|
|
66789
|
+
}
|
|
66288
66790
|
: {}),
|
|
66289
|
-
...(Array.isArray(
|
|
66290
|
-
|
|
66791
|
+
...(Array.isArray(sharedWorkspace.sidebarLayout) &&
|
|
66792
|
+
sharedWorkspace.sidebarLayout.length > 0
|
|
66291
66793
|
? {
|
|
66292
|
-
sidebarLayout:
|
|
66794
|
+
sidebarLayout: sharedWorkspace.sidebarLayout,
|
|
66293
66795
|
sidebarEnabled: workspace.sidebarEnabled !== false,
|
|
66294
66796
|
}
|
|
66295
66797
|
: {}),
|
|
@@ -66420,6 +66922,7 @@ async function prepareDashboardForPublish$1(
|
|
|
66420
66922
|
repository: options.repository || "",
|
|
66421
66923
|
appOrigin: appId,
|
|
66422
66924
|
visibility: options.visibility || "public",
|
|
66925
|
+
version: nextVersion,
|
|
66423
66926
|
});
|
|
66424
66927
|
|
|
66425
66928
|
// 9. Show save dialog for the publish package
|
|
@@ -66467,6 +66970,35 @@ async function prepareDashboardForPublish$1(
|
|
|
66467
66970
|
console.log(
|
|
66468
66971
|
`[DashboardConfigController] Published to registry: ${registrySubmission.registryUrl}`,
|
|
66469
66972
|
);
|
|
66973
|
+
// Persist the resolved next version back onto the workspace
|
|
66974
|
+
// so the NEXT publish resolves from it. Without this, the
|
|
66975
|
+
// publisher would have to re-enter the same version every
|
|
66976
|
+
// time (or keep bumping from 1.0.0, masking that the
|
|
66977
|
+
// registry already advanced).
|
|
66978
|
+
try {
|
|
66979
|
+
const workspaceController = workspaceController_1;
|
|
66980
|
+
const nextWorkspace = {
|
|
66981
|
+
...workspace,
|
|
66982
|
+
_dashboardConfig: {
|
|
66983
|
+
...(workspace._dashboardConfig || {}),
|
|
66984
|
+
version: nextVersion,
|
|
66985
|
+
registryPackage: manifest.name,
|
|
66986
|
+
registryScope: manifest.scope || manifest.githubUser,
|
|
66987
|
+
},
|
|
66988
|
+
};
|
|
66989
|
+
workspaceController.saveWorkspaceForApplication(
|
|
66990
|
+
win,
|
|
66991
|
+
appId,
|
|
66992
|
+
nextWorkspace,
|
|
66993
|
+
);
|
|
66994
|
+
} catch (persistErr) {
|
|
66995
|
+
// Non-fatal — registry is the source of truth for
|
|
66996
|
+
// latestVersion, so the next publish can still resolve
|
|
66997
|
+
// against it if this workspace write fails.
|
|
66998
|
+
console.warn(
|
|
66999
|
+
`[DashboardConfigController] Version persistence failed (continuing): ${persistErr.message}`,
|
|
67000
|
+
);
|
|
67001
|
+
}
|
|
66470
67002
|
} else {
|
|
66471
67003
|
console.warn(
|
|
66472
67004
|
`[DashboardConfigController] Registry publish failed: ${registrySubmission.error}`,
|
|
@@ -72931,120 +73463,6 @@ var dashboardRatingsController = {
|
|
|
72931
73463
|
enrichPackagesWithRatings: enrichPackagesWithRatings$1,
|
|
72932
73464
|
};
|
|
72933
73465
|
|
|
72934
|
-
/**
|
|
72935
|
-
* widgetPublishManifest.js
|
|
72936
|
-
*
|
|
72937
|
-
* Pure helpers for widget-publish flow — version bumping, package-name
|
|
72938
|
-
* parsing, and manifest generation. No electron / fs / adm-zip deps so
|
|
72939
|
-
* these can be unit-tested directly.
|
|
72940
|
-
*/
|
|
72941
|
-
|
|
72942
|
-
const SEMVER_RE =
|
|
72943
|
-
/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
72944
|
-
|
|
72945
|
-
function bumpVersion(current, type) {
|
|
72946
|
-
if (!current || typeof current !== "string") return "1.0.0";
|
|
72947
|
-
const match = current.match(SEMVER_RE);
|
|
72948
|
-
if (!match) return current;
|
|
72949
|
-
let [, major, minor, patch] = match;
|
|
72950
|
-
major = Number(major);
|
|
72951
|
-
minor = Number(minor);
|
|
72952
|
-
patch = Number(patch);
|
|
72953
|
-
switch (type) {
|
|
72954
|
-
case "major":
|
|
72955
|
-
return `${major + 1}.0.0`;
|
|
72956
|
-
case "minor":
|
|
72957
|
-
return `${major}.${minor + 1}.0`;
|
|
72958
|
-
case "patch":
|
|
72959
|
-
default:
|
|
72960
|
-
return `${major}.${minor}.${patch + 1}`;
|
|
72961
|
-
}
|
|
72962
|
-
}
|
|
72963
|
-
|
|
72964
|
-
function resolveNextVersion$1(currentVersion, options = {}) {
|
|
72965
|
-
if (options.version) return options.version;
|
|
72966
|
-
if (options.bump) return bumpVersion(currentVersion, options.bump);
|
|
72967
|
-
return currentVersion;
|
|
72968
|
-
}
|
|
72969
|
-
|
|
72970
|
-
function parsePackageName$1(pkgName) {
|
|
72971
|
-
if (!pkgName) return { scope: null, name: "" };
|
|
72972
|
-
const m = pkgName.match(/^@([^/]+)\/(.+)$/);
|
|
72973
|
-
if (m) return { scope: m[1], name: m[2] };
|
|
72974
|
-
return { scope: null, name: pkgName };
|
|
72975
|
-
}
|
|
72976
|
-
|
|
72977
|
-
function generateWidgetRegistryManifest$1(
|
|
72978
|
-
packageJson,
|
|
72979
|
-
widgetConfigs,
|
|
72980
|
-
options = {},
|
|
72981
|
-
) {
|
|
72982
|
-
const parsed = parsePackageName$1(packageJson.name || "");
|
|
72983
|
-
const scope = options.scope || parsed.scope || "";
|
|
72984
|
-
const name = options.name || parsed.name || packageJson.name || "";
|
|
72985
|
-
const version = options.version || packageJson.version || "1.0.0";
|
|
72986
|
-
const visibility = options.visibility === "private" ? "private" : "public";
|
|
72987
|
-
|
|
72988
|
-
const providerKeys = new Set();
|
|
72989
|
-
const providers = [];
|
|
72990
|
-
for (const cfg of widgetConfigs || []) {
|
|
72991
|
-
if (!Array.isArray(cfg.providers)) continue;
|
|
72992
|
-
for (const p of cfg.providers) {
|
|
72993
|
-
const key = `${p.type}:${p.providerClass || "mcp"}`;
|
|
72994
|
-
if (providerKeys.has(key)) continue;
|
|
72995
|
-
providerKeys.add(key);
|
|
72996
|
-
providers.push({
|
|
72997
|
-
type: p.type,
|
|
72998
|
-
required: p.required !== false,
|
|
72999
|
-
providerClass: p.providerClass || "mcp",
|
|
73000
|
-
});
|
|
73001
|
-
}
|
|
73002
|
-
}
|
|
73003
|
-
|
|
73004
|
-
const widgets = (widgetConfigs || []).map((cfg) => ({
|
|
73005
|
-
name: cfg.component || cfg.name,
|
|
73006
|
-
displayName: cfg.name || cfg.component,
|
|
73007
|
-
description: cfg.description || "",
|
|
73008
|
-
icon: cfg.icon || "square",
|
|
73009
|
-
providers: Array.isArray(cfg.providers)
|
|
73010
|
-
? cfg.providers.map((p) => ({
|
|
73011
|
-
type: p.type,
|
|
73012
|
-
required: p.required !== false,
|
|
73013
|
-
providerClass: p.providerClass || "mcp",
|
|
73014
|
-
}))
|
|
73015
|
-
: [],
|
|
73016
|
-
}));
|
|
73017
|
-
|
|
73018
|
-
return {
|
|
73019
|
-
scope,
|
|
73020
|
-
name,
|
|
73021
|
-
displayName: options.displayName || packageJson.displayName || name,
|
|
73022
|
-
version,
|
|
73023
|
-
type: "widget",
|
|
73024
|
-
visibility,
|
|
73025
|
-
description: options.description || packageJson.description || "",
|
|
73026
|
-
author:
|
|
73027
|
-
options.authorName ||
|
|
73028
|
-
(typeof packageJson.author === "string"
|
|
73029
|
-
? packageJson.author
|
|
73030
|
-
: packageJson.author?.name || ""),
|
|
73031
|
-
category: options.category || "general",
|
|
73032
|
-
tags: Array.isArray(options.tags) ? options.tags : [],
|
|
73033
|
-
icon: options.icon || "puzzle-piece",
|
|
73034
|
-
providers,
|
|
73035
|
-
widgets,
|
|
73036
|
-
appOrigin: options.appOrigin || "",
|
|
73037
|
-
publishedAt: new Date().toISOString(),
|
|
73038
|
-
};
|
|
73039
|
-
}
|
|
73040
|
-
|
|
73041
|
-
var widgetPublishManifest = {
|
|
73042
|
-
bumpVersion,
|
|
73043
|
-
resolveNextVersion: resolveNextVersion$1,
|
|
73044
|
-
parsePackageName: parsePackageName$1,
|
|
73045
|
-
generateWidgetRegistryManifest: generateWidgetRegistryManifest$1,
|
|
73046
|
-
};
|
|
73047
|
-
|
|
73048
73466
|
/**
|
|
73049
73467
|
* widgetRegistryController.js
|
|
73050
73468
|
*
|
|
@@ -73074,7 +73492,7 @@ const {
|
|
|
73074
73492
|
resolveNextVersion,
|
|
73075
73493
|
parsePackageName,
|
|
73076
73494
|
generateWidgetRegistryManifest,
|
|
73077
|
-
} =
|
|
73495
|
+
} = requireWidgetPublishManifest();
|
|
73078
73496
|
|
|
73079
73497
|
/**
|
|
73080
73498
|
* Resilient widget lookup. Callers pass identifiers in different shapes —
|
|
@@ -73550,6 +73968,7 @@ const {
|
|
|
73550
73968
|
prepareThemeForPublish,
|
|
73551
73969
|
installThemeFromRegistry,
|
|
73552
73970
|
getThemePublishPreview,
|
|
73971
|
+
checkThemeUpdatesForApp,
|
|
73553
73972
|
} = themeRegistryController$1;
|
|
73554
73973
|
const {
|
|
73555
73974
|
prepareWidgetForPublish,
|
|
@@ -73643,6 +74062,7 @@ var controller = {
|
|
|
73643
74062
|
prepareThemeForPublish,
|
|
73644
74063
|
installThemeFromRegistry,
|
|
73645
74064
|
getThemePublishPreview,
|
|
74065
|
+
checkThemeUpdatesForApp,
|
|
73646
74066
|
prepareWidgetForPublish,
|
|
73647
74067
|
inspectWidgetPackage,
|
|
73648
74068
|
assignRoles,
|