@trops/dash-core 0.1.428 → 0.1.431
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 +366 -42
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +338 -55
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +338 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -472,6 +472,7 @@ const REGISTRY_SEARCH_DASHBOARDS = "registry:search-dashboards";
|
|
|
472
472
|
const REGISTRY_SEARCH_THEMES = "registry:search-themes";
|
|
473
473
|
const REGISTRY_PUBLISH_WIDGET = "registry:publish-widget";
|
|
474
474
|
const REGISTRY_INSPECT_WIDGET_PACKAGE = "registry:inspect-widget-package";
|
|
475
|
+
const REGISTRY_SCAN_WIDGET_DEFAULTS = "registry:scan-widget-defaults";
|
|
475
476
|
const REGISTRY_PREVIEW_FETCH = "registry:preview-fetch";
|
|
476
477
|
|
|
477
478
|
var registryEvents$1 = {
|
|
@@ -483,6 +484,7 @@ var registryEvents$1 = {
|
|
|
483
484
|
REGISTRY_SEARCH_THEMES,
|
|
484
485
|
REGISTRY_PUBLISH_WIDGET,
|
|
485
486
|
REGISTRY_INSPECT_WIDGET_PACKAGE,
|
|
487
|
+
REGISTRY_SCAN_WIDGET_DEFAULTS,
|
|
486
488
|
REGISTRY_PREVIEW_FETCH,
|
|
487
489
|
};
|
|
488
490
|
|
|
@@ -27268,7 +27270,7 @@ function findWidgetsDir$2(widgetPath) {
|
|
|
27268
27270
|
* @param {string} widgetPath - Absolute path to the widget directory
|
|
27269
27271
|
* @returns {Promise<string|null>} Path to the compiled bundle, or null if nothing to compile
|
|
27270
27272
|
*/
|
|
27271
|
-
async function compileWidget(widgetPath) {
|
|
27273
|
+
async function compileWidget$1(widgetPath) {
|
|
27272
27274
|
const widgetsDir = findWidgetsDir$2(widgetPath);
|
|
27273
27275
|
|
|
27274
27276
|
if (!widgetsDir) {
|
|
@@ -27400,7 +27402,7 @@ async function compileWidget(widgetPath) {
|
|
|
27400
27402
|
}
|
|
27401
27403
|
}
|
|
27402
27404
|
|
|
27403
|
-
var widgetCompiler$1 = { compileWidget, findWidgetsDir: findWidgetsDir$2 };
|
|
27405
|
+
var widgetCompiler$1 = { compileWidget: compileWidget$1, findWidgetsDir: findWidgetsDir$2 };
|
|
27404
27406
|
|
|
27405
27407
|
/**
|
|
27406
27408
|
* Dynamic Widget Loader
|
|
@@ -29416,25 +29418,31 @@ var schedulerController_1 = schedulerController$2;
|
|
|
29416
29418
|
|
|
29417
29419
|
let bundlePath = findBundlePath(widget.path);
|
|
29418
29420
|
|
|
29419
|
-
// Auto-compile if no bundle exists (
|
|
29421
|
+
// Auto-compile if no bundle exists (registry installs ship the
|
|
29422
|
+
// bundle pre-compiled, so this fallback only fires for older
|
|
29423
|
+
// packages or local installs).
|
|
29424
|
+
let compileError = null;
|
|
29420
29425
|
if (!bundlePath) {
|
|
29421
29426
|
try {
|
|
29422
29427
|
const compiled = await compileWidget(widget.path);
|
|
29423
29428
|
if (compiled) {
|
|
29424
29429
|
bundlePath = compiled;
|
|
29425
29430
|
}
|
|
29426
|
-
} catch (
|
|
29427
|
-
|
|
29428
|
-
|
|
29429
|
-
|
|
29430
|
-
|
|
29431
|
+
} catch (err) {
|
|
29432
|
+
compileError = err;
|
|
29433
|
+
// dash-core's electron build strips console.* — surface
|
|
29434
|
+
// the actual cause through the IPC return so the renderer
|
|
29435
|
+
// can show it to the user.
|
|
29431
29436
|
}
|
|
29432
29437
|
}
|
|
29433
29438
|
|
|
29434
29439
|
if (!bundlePath) {
|
|
29440
|
+
const detail = compileError
|
|
29441
|
+
? ` (auto-compile failed: ${compileError.message})`
|
|
29442
|
+
: "";
|
|
29435
29443
|
return {
|
|
29436
29444
|
success: false,
|
|
29437
|
-
error: `No bundle found in: ${widget.path}`,
|
|
29445
|
+
error: `No bundle found in: ${widget.path}${detail}`,
|
|
29438
29446
|
};
|
|
29439
29447
|
}
|
|
29440
29448
|
|
|
@@ -64502,6 +64510,74 @@ function stripPersonalizationFromWorkspace$1(workspace) {
|
|
|
64502
64510
|
return cleaned;
|
|
64503
64511
|
}
|
|
64504
64512
|
|
|
64513
|
+
/**
|
|
64514
|
+
* Remap each layout item's `packageId` from a local-only scope (e.g.
|
|
64515
|
+
* `@ai-built/foo`) to the caller's published scope (`@<callerScope>/foo`)
|
|
64516
|
+
* so the installer's ComponentManager — which registers widgets under
|
|
64517
|
+
* the published scope — can look them up.
|
|
64518
|
+
*
|
|
64519
|
+
* Mirrors the scope-remap that `generateRegistryManifest` already does
|
|
64520
|
+
* for the dashboard's widget DEPENDENCIES list. Without this, the deps
|
|
64521
|
+
* list is correct (`@callerScope/foo`) but the per-instance layout
|
|
64522
|
+
* items still say `packageId: "@ai-built/foo"` — every Dependencies
|
|
64523
|
+
* tab + publish-flow attribution on the installer's machine misses.
|
|
64524
|
+
*
|
|
64525
|
+
* Returns a deep copy. Idempotent: items already under the caller
|
|
64526
|
+
* scope (or any non-local scope) pass through untouched.
|
|
64527
|
+
*
|
|
64528
|
+
* @param {Object} workspace
|
|
64529
|
+
* @param {string} callerScope - Publisher's registry username (e.g. "trops")
|
|
64530
|
+
* @param {string[]} [localOnlyScopes=["ai-built"]] - Scopes that must be remapped
|
|
64531
|
+
*/
|
|
64532
|
+
function remapLayoutPackageScopes$1(
|
|
64533
|
+
workspace,
|
|
64534
|
+
callerScope,
|
|
64535
|
+
localOnlyScopes = ["ai-built"],
|
|
64536
|
+
) {
|
|
64537
|
+
if (!workspace || !callerScope) return workspace;
|
|
64538
|
+
const localScopeSet = new Set(
|
|
64539
|
+
localOnlyScopes.map((s) => String(s).replace(/^@/, "")),
|
|
64540
|
+
);
|
|
64541
|
+
const remapPackageId = (pkgId) => {
|
|
64542
|
+
if (typeof pkgId !== "string" || pkgId.length === 0) return pkgId;
|
|
64543
|
+
// Match `@<scope>/<rest>` or `<scope>/<rest>`. Tolerant of either form.
|
|
64544
|
+
const m = pkgId.match(/^@?([^/]+)\/(.+)$/);
|
|
64545
|
+
if (!m) return pkgId;
|
|
64546
|
+
const scope = m[1];
|
|
64547
|
+
const rest = m[2];
|
|
64548
|
+
if (!localScopeSet.has(scope)) return pkgId;
|
|
64549
|
+
return `@${callerScope.replace(/^@/, "")}/${rest}`;
|
|
64550
|
+
};
|
|
64551
|
+
const remapItem = (item) => {
|
|
64552
|
+
if (!item || typeof item !== "object") return item;
|
|
64553
|
+
const next = { ...item };
|
|
64554
|
+
if (item.packageId) {
|
|
64555
|
+
const remapped = remapPackageId(item.packageId);
|
|
64556
|
+
if (remapped !== item.packageId) next.packageId = remapped;
|
|
64557
|
+
}
|
|
64558
|
+
if (item._sourcePackage) {
|
|
64559
|
+
const remapped = remapPackageId(item._sourcePackage);
|
|
64560
|
+
if (remapped !== item._sourcePackage) next._sourcePackage = remapped;
|
|
64561
|
+
}
|
|
64562
|
+
if (Array.isArray(item.items)) next.items = item.items.map(remapItem);
|
|
64563
|
+
if (Array.isArray(item.layout)) next.layout = item.layout.map(remapItem);
|
|
64564
|
+
return next;
|
|
64565
|
+
};
|
|
64566
|
+
const next = { ...workspace };
|
|
64567
|
+
if (Array.isArray(next.layout)) next.layout = next.layout.map(remapItem);
|
|
64568
|
+
if (Array.isArray(next.sidebarLayout)) {
|
|
64569
|
+
next.sidebarLayout = next.sidebarLayout.map(remapItem);
|
|
64570
|
+
}
|
|
64571
|
+
if (Array.isArray(next.pages)) {
|
|
64572
|
+
next.pages = next.pages.map((page) =>
|
|
64573
|
+
page && Array.isArray(page.layout)
|
|
64574
|
+
? { ...page, layout: page.layout.map(remapItem) }
|
|
64575
|
+
: page,
|
|
64576
|
+
);
|
|
64577
|
+
}
|
|
64578
|
+
return next;
|
|
64579
|
+
}
|
|
64580
|
+
|
|
64505
64581
|
var dashboardConfigUtils$1 = {
|
|
64506
64582
|
collectComponentNames: collectComponentNames$1,
|
|
64507
64583
|
collectComponentNamesFromWorkspace: collectComponentNamesFromWorkspace$1,
|
|
@@ -64518,6 +64594,7 @@ var dashboardConfigUtils$1 = {
|
|
|
64518
64594
|
buildProviderSetupManifest,
|
|
64519
64595
|
checkApiCompatibility,
|
|
64520
64596
|
stripPersonalizationFromWorkspace: stripPersonalizationFromWorkspace$1,
|
|
64597
|
+
remapLayoutPackageScopes: remapLayoutPackageScopes$1,
|
|
64521
64598
|
};
|
|
64522
64599
|
|
|
64523
64600
|
/**
|
|
@@ -65559,6 +65636,7 @@ const {
|
|
|
65559
65636
|
buildProviderRequirements,
|
|
65560
65637
|
applyEventWiringToLayout,
|
|
65561
65638
|
stripPersonalizationFromWorkspace,
|
|
65639
|
+
remapLayoutPackageScopes,
|
|
65562
65640
|
} = dashboardConfigUtils$1;
|
|
65563
65641
|
const { searchRegistry, getPackage } = registryController$3;
|
|
65564
65642
|
const { getStoredToken, clearToken } = registryAuthController$2;
|
|
@@ -66978,7 +67056,33 @@ async function prepareDashboardForPublish$1(
|
|
|
66978
67056
|
// widget's own `defaultValue` on each field never gets a chance.
|
|
66979
67057
|
// Layout position, ordering, nested containers, and any title text
|
|
66980
67058
|
// are preserved (they're part of the template, not personal).
|
|
66981
|
-
|
|
67059
|
+
let sharedWorkspace = stripPersonalizationFromWorkspace(workspace);
|
|
67060
|
+
|
|
67061
|
+
// Remap layout-item `packageId` from any local-only scope (e.g.
|
|
67062
|
+
// `@ai-built/foo`) to the publisher's scope (`@<callerScope>/foo`).
|
|
67063
|
+
// The widget-deps array in the dashboard manifest already gets
|
|
67064
|
+
// remapped (see generateRegistryManifest), but the per-instance
|
|
67065
|
+
// `packageId` on the layout items themselves was being shipped
|
|
67066
|
+
// as-is — so installers' ComponentManager (which registers
|
|
67067
|
+
// widgets under the published scope) couldn't reverse-look-up by
|
|
67068
|
+
// `packageId` on a layout item, breaking the Dependencies tab and
|
|
67069
|
+
// the publish-flow attribution on chained republishes.
|
|
67070
|
+
let resolvedCallerScope = options.callerScope || options.githubUser || "";
|
|
67071
|
+
if (!resolvedCallerScope) {
|
|
67072
|
+
try {
|
|
67073
|
+
const { getRegistryProfile } = registryAuthController$2;
|
|
67074
|
+
const profile = await getRegistryProfile();
|
|
67075
|
+
resolvedCallerScope = profile?.username || options.authorId || "";
|
|
67076
|
+
} catch {
|
|
67077
|
+
resolvedCallerScope = options.authorId || "";
|
|
67078
|
+
}
|
|
67079
|
+
}
|
|
67080
|
+
if (resolvedCallerScope) {
|
|
67081
|
+
sharedWorkspace = remapLayoutPackageScopes(
|
|
67082
|
+
sharedWorkspace,
|
|
67083
|
+
resolvedCallerScope,
|
|
67084
|
+
);
|
|
67085
|
+
}
|
|
66982
67086
|
const layout = sharedWorkspace.layout || [];
|
|
66983
67087
|
|
|
66984
67088
|
// 3. Build the dashboard config — walk main + pages + sidebar
|
|
@@ -73729,7 +73833,7 @@ const {
|
|
|
73729
73833
|
} = registryAuthController$2;
|
|
73730
73834
|
const widgetRegistryModule = widgetRegistryExports;
|
|
73731
73835
|
const { dynamicWidgetLoader: dynamicWidgetLoader$1 } = dynamicWidgetLoaderExports;
|
|
73732
|
-
const { findWidgetsDir } = widgetCompiler$1;
|
|
73836
|
+
const { findWidgetsDir, compileWidget } = widgetCompiler$1;
|
|
73733
73837
|
const {
|
|
73734
73838
|
resolveNextVersion,
|
|
73735
73839
|
parsePackageName,
|
|
@@ -73790,11 +73894,160 @@ async function scanWidgetConfigs(widgetPath) {
|
|
|
73790
73894
|
}
|
|
73791
73895
|
}
|
|
73792
73896
|
|
|
73897
|
+
// ─── Publish-time defaults scan + staged rewrite ─────────────────────────────
|
|
73898
|
+
|
|
73899
|
+
/**
|
|
73900
|
+
* Scan a widget package's `.dash.js` files and return every non-empty
|
|
73901
|
+
* `userConfig[field].defaultValue` as a structured ref. Powers the
|
|
73902
|
+
* publish modal's "Verify defaults" step — surfaces values the
|
|
73903
|
+
* developer set during testing (regional paths, test tokens, etc.)
|
|
73904
|
+
* so the publisher can keep, blank, or edit each one before the ZIP
|
|
73905
|
+
* ships.
|
|
73906
|
+
*
|
|
73907
|
+
* @param {string} packageId e.g. "@ai-built/pipeline"
|
|
73908
|
+
* @returns {Promise<{success: boolean, defaults: Array, error?: string}>}
|
|
73909
|
+
*/
|
|
73910
|
+
async function scanWidgetDefaults$1(packageId) {
|
|
73911
|
+
try {
|
|
73912
|
+
const registry = widgetRegistryModule.getWidgetRegistry();
|
|
73913
|
+
const widget = findWidget(registry, packageId);
|
|
73914
|
+
if (!widget || !widget.path) {
|
|
73915
|
+
return {
|
|
73916
|
+
success: false,
|
|
73917
|
+
error: `Widget package not found locally: ${packageId}`,
|
|
73918
|
+
};
|
|
73919
|
+
}
|
|
73920
|
+
|
|
73921
|
+
const configs = await scanWidgetConfigs(widget.path);
|
|
73922
|
+
const defaults = [];
|
|
73923
|
+
for (const cfg of configs) {
|
|
73924
|
+
const widgetName = cfg.component || cfg.name;
|
|
73925
|
+
if (!widgetName) continue;
|
|
73926
|
+
const userConfig = cfg.userConfig;
|
|
73927
|
+
if (!userConfig || typeof userConfig !== "object") continue;
|
|
73928
|
+
for (const [field, spec] of Object.entries(userConfig)) {
|
|
73929
|
+
if (!spec || typeof spec !== "object") continue;
|
|
73930
|
+
const value = spec.defaultValue;
|
|
73931
|
+
// "non-empty" = not nullish, not empty-string. `false` and `0`
|
|
73932
|
+
// are legitimate defaults (checkbox-off, numeric zero) so we
|
|
73933
|
+
// keep them. Arrays/objects only surface if non-empty.
|
|
73934
|
+
const isEmpty =
|
|
73935
|
+
value === null ||
|
|
73936
|
+
value === undefined ||
|
|
73937
|
+
value === "" ||
|
|
73938
|
+
(Array.isArray(value) && value.length === 0) ||
|
|
73939
|
+
(typeof value === "object" &&
|
|
73940
|
+
!Array.isArray(value) &&
|
|
73941
|
+
Object.keys(value).length === 0);
|
|
73942
|
+
if (isEmpty) continue;
|
|
73943
|
+
defaults.push({
|
|
73944
|
+
widgetName,
|
|
73945
|
+
field,
|
|
73946
|
+
currentDefault: value,
|
|
73947
|
+
displayName: spec.displayName || field,
|
|
73948
|
+
type: spec.type || "text",
|
|
73949
|
+
instructions: spec.instructions || "",
|
|
73950
|
+
});
|
|
73951
|
+
}
|
|
73952
|
+
}
|
|
73953
|
+
return { success: true, defaults };
|
|
73954
|
+
} catch (error) {
|
|
73955
|
+
console.error("[widgetRegistry] scanWidgetDefaults failed:", error);
|
|
73956
|
+
return { success: false, error: error.message };
|
|
73957
|
+
}
|
|
73958
|
+
}
|
|
73959
|
+
|
|
73960
|
+
/**
|
|
73961
|
+
* Return the exported-default object from a `.dash.js` serialized as
|
|
73962
|
+
* pretty-printed JS. We use JSON.stringify (plus a couple of minor
|
|
73963
|
+
* touch-ups) because dash configs are pure data — no functions, no
|
|
73964
|
+
* imports, no regex literals. The source file shape we emit matches
|
|
73965
|
+
* the scaffolded template so dynamicWidgetLoader reads it back
|
|
73966
|
+
* unchanged.
|
|
73967
|
+
*/
|
|
73968
|
+
function serializeDashConfig(config) {
|
|
73969
|
+
const json = JSON.stringify(config, null, 4);
|
|
73970
|
+
return `export default ${json};\n`;
|
|
73971
|
+
}
|
|
73972
|
+
|
|
73973
|
+
/**
|
|
73974
|
+
* Copy a source widget directory into `dstDir`, then rewrite the
|
|
73975
|
+
* `userConfig[field].defaultValue` for every entry in `overrides`.
|
|
73976
|
+
* `overrides` shape: `{ [widgetName]: { [field]: newValue } }`.
|
|
73977
|
+
*
|
|
73978
|
+
* Returns the list of files that were actually rewritten (useful for
|
|
73979
|
+
* the UI / logs). Pure file-system side effect; does NOT touch the
|
|
73980
|
+
* original source directory.
|
|
73981
|
+
*/
|
|
73982
|
+
async function stageOverrides(srcDir, dstDir, overrides) {
|
|
73983
|
+
// Copy the whole package tree into dstDir.
|
|
73984
|
+
fs.cpSync(srcDir, dstDir, {
|
|
73985
|
+
recursive: true,
|
|
73986
|
+
filter: (src) => {
|
|
73987
|
+
const base = path.basename(src);
|
|
73988
|
+
if (ZIP_EXCLUDE_DIRS.has(base)) return false;
|
|
73989
|
+
if (base.startsWith(".")) return false;
|
|
73990
|
+
return true;
|
|
73991
|
+
},
|
|
73992
|
+
});
|
|
73993
|
+
|
|
73994
|
+
if (!overrides || Object.keys(overrides).length === 0) return [];
|
|
73995
|
+
|
|
73996
|
+
const widgetsDir = findWidgetsDir(dstDir) || path.join(dstDir, "widgets");
|
|
73997
|
+
if (!fs.existsSync(widgetsDir)) return [];
|
|
73998
|
+
|
|
73999
|
+
const rewritten = [];
|
|
74000
|
+
const files = fs.readdirSync(widgetsDir);
|
|
74001
|
+
for (const file of files) {
|
|
74002
|
+
if (!file.endsWith(".dash.js")) continue;
|
|
74003
|
+
const filePath = path.join(widgetsDir, file);
|
|
74004
|
+
let cfg;
|
|
74005
|
+
try {
|
|
74006
|
+
// eslint-disable-next-line no-await-in-loop
|
|
74007
|
+
cfg = await dynamicWidgetLoader$1.loadConfigFile(filePath);
|
|
74008
|
+
} catch (err) {
|
|
74009
|
+
console.warn(
|
|
74010
|
+
`[widgetRegistry] Could not load ${file} for override: ${err.message}`,
|
|
74011
|
+
);
|
|
74012
|
+
continue;
|
|
74013
|
+
}
|
|
74014
|
+
if (!cfg || typeof cfg !== "object") continue;
|
|
74015
|
+
const widgetName = cfg.component || cfg.name;
|
|
74016
|
+
if (!widgetName || !overrides[widgetName]) continue;
|
|
74017
|
+
const fieldOverrides = overrides[widgetName];
|
|
74018
|
+
|
|
74019
|
+
if (!cfg.userConfig || typeof cfg.userConfig !== "object") continue;
|
|
74020
|
+
let changed = false;
|
|
74021
|
+
for (const [field, newValue] of Object.entries(fieldOverrides)) {
|
|
74022
|
+
if (!cfg.userConfig[field] || typeof cfg.userConfig[field] !== "object") {
|
|
74023
|
+
continue;
|
|
74024
|
+
}
|
|
74025
|
+
// Undefined = "no change" from the UI side. Explicit null / ""
|
|
74026
|
+
// = user wants to blank it out.
|
|
74027
|
+
if (newValue === undefined) continue;
|
|
74028
|
+
cfg.userConfig[field] = {
|
|
74029
|
+
...cfg.userConfig[field],
|
|
74030
|
+
defaultValue: newValue,
|
|
74031
|
+
};
|
|
74032
|
+
changed = true;
|
|
74033
|
+
}
|
|
74034
|
+
if (!changed) continue;
|
|
74035
|
+
|
|
74036
|
+
fs.writeFileSync(filePath, serializeDashConfig(cfg));
|
|
74037
|
+
rewritten.push(file);
|
|
74038
|
+
}
|
|
74039
|
+
return rewritten;
|
|
74040
|
+
}
|
|
74041
|
+
|
|
73793
74042
|
// ─── ZIP builder ─────────────────────────────────────────────────────────────
|
|
73794
74043
|
|
|
74044
|
+
// `dist` is intentionally NOT excluded — the publish flow runs
|
|
74045
|
+
// `compileWidget` against the staged package right before zipping so
|
|
74046
|
+
// the installer doesn't have to recompile (and fail silently because
|
|
74047
|
+
// `console.*` is stripped from dash-core's electron build, masking
|
|
74048
|
+
// any esbuild error). Shipping the bundle makes install zero-config.
|
|
73795
74049
|
const ZIP_EXCLUDE_DIRS = new Set([
|
|
73796
74050
|
"node_modules",
|
|
73797
|
-
"dist",
|
|
73798
74051
|
".git",
|
|
73799
74052
|
".DS_Store",
|
|
73800
74053
|
".next",
|
|
@@ -73983,45 +74236,92 @@ async function prepareWidgetForPublish$1(appId, packageId, options = {}) {
|
|
|
73983
74236
|
appOrigin: appId,
|
|
73984
74237
|
});
|
|
73985
74238
|
|
|
73986
|
-
// 7. Zip the widget directory to a temp file
|
|
74239
|
+
// 7. Zip the widget directory to a temp file. When the caller
|
|
74240
|
+
// supplied `defaultsOverride`, stage a copy of the package
|
|
74241
|
+
// under os.tmpdir() and rewrite the targeted
|
|
74242
|
+
// `userConfig[field].defaultValue` entries there before
|
|
74243
|
+
// zipping — source files on the publisher's machine stay
|
|
74244
|
+
// untouched.
|
|
73987
74245
|
const zipName = `widget-${manifest.scope}-${manifest.name}-v${manifest.version}.zip`;
|
|
73988
74246
|
const zipPath = path.join(app.getPath("temp"), zipName);
|
|
73989
|
-
const
|
|
73990
|
-
|
|
73991
|
-
|
|
74247
|
+
const hasOverrides =
|
|
74248
|
+
options.defaultsOverride &&
|
|
74249
|
+
typeof options.defaultsOverride === "object" &&
|
|
74250
|
+
Object.keys(options.defaultsOverride).length > 0;
|
|
74251
|
+
const stagedDir = hasOverrides
|
|
74252
|
+
? fs.mkdtempSync(path.join(app.getPath("temp"), `dash-publish-stage-`))
|
|
74253
|
+
: null;
|
|
74254
|
+
let registryResult;
|
|
74255
|
+
try {
|
|
74256
|
+
let sourceDir = widget.path;
|
|
74257
|
+
if (stagedDir) {
|
|
74258
|
+
await stageOverrides(widget.path, stagedDir, options.defaultsOverride);
|
|
74259
|
+
sourceDir = stagedDir;
|
|
74260
|
+
}
|
|
73992
74261
|
|
|
73993
|
-
|
|
73994
|
-
|
|
73995
|
-
|
|
73996
|
-
|
|
73997
|
-
|
|
74262
|
+
// Compile the widget into `dist/index.cjs.js` before zipping.
|
|
74263
|
+
// The installer also runs compileWidget at first-load, but
|
|
74264
|
+
// dash-core strips `console.*` from its electron bundle, so any
|
|
74265
|
+
// esbuild error during install-time compile vanishes silently
|
|
74266
|
+
// and the user just sees `No bundle found`. Compiling at
|
|
74267
|
+
// publish time (where errors WILL surface to the publisher who
|
|
74268
|
+
// can fix them) and shipping the bundle in the ZIP makes
|
|
74269
|
+
// install zero-config.
|
|
74270
|
+
try {
|
|
74271
|
+
await compileWidget(sourceDir);
|
|
74272
|
+
} catch (compileErr) {
|
|
74273
|
+
return {
|
|
74274
|
+
success: false,
|
|
74275
|
+
error: `Widget compilation failed: ${compileErr.message}. Fix the source error and republish; otherwise installers won't be able to load the widget.`,
|
|
74276
|
+
manifest,
|
|
74277
|
+
};
|
|
74278
|
+
}
|
|
74279
|
+
|
|
74280
|
+
const zip = new AdmZip();
|
|
74281
|
+
addDirToZip(zip, sourceDir);
|
|
74282
|
+
zip.writeZip(zipPath);
|
|
74283
|
+
|
|
74284
|
+
// 8. Publish to registry
|
|
74285
|
+
registryResult = await registryApiController$1.publishToRegistry(
|
|
74286
|
+
zipPath,
|
|
74287
|
+
manifest,
|
|
74288
|
+
);
|
|
74289
|
+
|
|
74290
|
+
// 9. On failure: revert package.json (if we bumped) and surface details
|
|
74291
|
+
if (!registryResult.success) {
|
|
74292
|
+
if (newVersion !== previousVersion) {
|
|
74293
|
+
try {
|
|
74294
|
+
pkgJson.version = previousVersion;
|
|
74295
|
+
fs.writeFileSync(
|
|
74296
|
+
pkgJsonPath,
|
|
74297
|
+
JSON.stringify(pkgJson, null, 2) + "\n",
|
|
74298
|
+
);
|
|
74299
|
+
} catch {
|
|
74300
|
+
/* best effort */
|
|
74301
|
+
}
|
|
74302
|
+
}
|
|
74303
|
+
return {
|
|
74304
|
+
success: false,
|
|
74305
|
+
error: registryResult.error,
|
|
74306
|
+
details: registryResult.details,
|
|
74307
|
+
manifest,
|
|
74308
|
+
};
|
|
74309
|
+
}
|
|
73998
74310
|
|
|
73999
|
-
|
|
74000
|
-
|
|
74001
|
-
|
|
74311
|
+
// Clean up the temp zip on success.
|
|
74312
|
+
try {
|
|
74313
|
+
fs.unlinkSync(zipPath);
|
|
74314
|
+
} catch {
|
|
74315
|
+
/* ignore */
|
|
74316
|
+
}
|
|
74317
|
+
} finally {
|
|
74318
|
+
if (stagedDir) {
|
|
74002
74319
|
try {
|
|
74003
|
-
|
|
74004
|
-
fs.writeFileSync(
|
|
74005
|
-
pkgJsonPath,
|
|
74006
|
-
JSON.stringify(pkgJson, null, 2) + "\n",
|
|
74007
|
-
);
|
|
74320
|
+
fs.rmSync(stagedDir, { recursive: true, force: true });
|
|
74008
74321
|
} catch {
|
|
74009
74322
|
/* best effort */
|
|
74010
74323
|
}
|
|
74011
74324
|
}
|
|
74012
|
-
return {
|
|
74013
|
-
success: false,
|
|
74014
|
-
error: registryResult.error,
|
|
74015
|
-
details: registryResult.details,
|
|
74016
|
-
manifest,
|
|
74017
|
-
};
|
|
74018
|
-
}
|
|
74019
|
-
|
|
74020
|
-
// Clean up the temp zip
|
|
74021
|
-
try {
|
|
74022
|
-
fs.unlinkSync(zipPath);
|
|
74023
|
-
} catch {
|
|
74024
|
-
/* ignore */
|
|
74025
74325
|
}
|
|
74026
74326
|
|
|
74027
74327
|
return {
|
|
@@ -74098,6 +74398,7 @@ async function inspectWidgetPackage$1(packageId) {
|
|
|
74098
74398
|
var widgetRegistryController = {
|
|
74099
74399
|
prepareWidgetForPublish: prepareWidgetForPublish$1,
|
|
74100
74400
|
inspectWidgetPackage: inspectWidgetPackage$1,
|
|
74401
|
+
scanWidgetDefaults: scanWidgetDefaults$1,
|
|
74101
74402
|
};
|
|
74102
74403
|
|
|
74103
74404
|
/**
|
|
@@ -74215,6 +74516,7 @@ const {
|
|
|
74215
74516
|
const {
|
|
74216
74517
|
prepareWidgetForPublish,
|
|
74217
74518
|
inspectWidgetPackage,
|
|
74519
|
+
scanWidgetDefaults,
|
|
74218
74520
|
} = widgetRegistryController;
|
|
74219
74521
|
const {
|
|
74220
74522
|
assignRoles,
|
|
@@ -74307,6 +74609,7 @@ var controller = {
|
|
|
74307
74609
|
checkThemeUpdatesForApp,
|
|
74308
74610
|
prepareWidgetForPublish,
|
|
74309
74611
|
inspectWidgetPackage,
|
|
74612
|
+
scanWidgetDefaults,
|
|
74310
74613
|
assignRoles,
|
|
74311
74614
|
matchTailwindFamily,
|
|
74312
74615
|
generateThemeFromPalette,
|
|
@@ -75456,6 +75759,27 @@ const registryApi$2 = {
|
|
|
75456
75759
|
}
|
|
75457
75760
|
},
|
|
75458
75761
|
|
|
75762
|
+
/**
|
|
75763
|
+
* Scan a widget package's `.dash.js` configs and return the list of
|
|
75764
|
+
* non-empty `userConfig[field].defaultValue` entries. Powers the
|
|
75765
|
+
* publish modal's "Verify defaults" step — lets the publisher
|
|
75766
|
+
* review (and optionally blank / edit) values set during
|
|
75767
|
+
* development before the ZIP ships.
|
|
75768
|
+
*
|
|
75769
|
+
* @param {string} packageId - Widget packageId (e.g. "@scope/name")
|
|
75770
|
+
* @returns {Promise<Object>} { success, defaults: [{widgetName, field, currentDefault, displayName, type, instructions}], error? }
|
|
75771
|
+
*/
|
|
75772
|
+
scanWidgetDefaults: async (packageId) => {
|
|
75773
|
+
try {
|
|
75774
|
+
return await ipcRenderer$h.invoke("registry:scan-widget-defaults", {
|
|
75775
|
+
packageId,
|
|
75776
|
+
});
|
|
75777
|
+
} catch (error) {
|
|
75778
|
+
console.error("[RegistryApi] Error scanning widget defaults:", error);
|
|
75779
|
+
throw error;
|
|
75780
|
+
}
|
|
75781
|
+
},
|
|
75782
|
+
|
|
75459
75783
|
/**
|
|
75460
75784
|
* Fetch a registry package's source (component + config + bundle) into a
|
|
75461
75785
|
* temp directory and return the source strings without installing the
|