@trops/dash-core 0.1.429 → 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.
@@ -27270,7 +27270,7 @@ function findWidgetsDir$2(widgetPath) {
27270
27270
  * @param {string} widgetPath - Absolute path to the widget directory
27271
27271
  * @returns {Promise<string|null>} Path to the compiled bundle, or null if nothing to compile
27272
27272
  */
27273
- async function compileWidget(widgetPath) {
27273
+ async function compileWidget$1(widgetPath) {
27274
27274
  const widgetsDir = findWidgetsDir$2(widgetPath);
27275
27275
 
27276
27276
  if (!widgetsDir) {
@@ -27402,7 +27402,7 @@ async function compileWidget(widgetPath) {
27402
27402
  }
27403
27403
  }
27404
27404
 
27405
- var widgetCompiler$1 = { compileWidget, findWidgetsDir: findWidgetsDir$2 };
27405
+ var widgetCompiler$1 = { compileWidget: compileWidget$1, findWidgetsDir: findWidgetsDir$2 };
27406
27406
 
27407
27407
  /**
27408
27408
  * Dynamic Widget Loader
@@ -29418,25 +29418,31 @@ var schedulerController_1 = schedulerController$2;
29418
29418
 
29419
29419
  let bundlePath = findBundlePath(widget.path);
29420
29420
 
29421
- // Auto-compile if no bundle exists (same as read-all-bundles)
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;
29422
29425
  if (!bundlePath) {
29423
29426
  try {
29424
29427
  const compiled = await compileWidget(widget.path);
29425
29428
  if (compiled) {
29426
29429
  bundlePath = compiled;
29427
29430
  }
29428
- } catch (compileError) {
29429
- console.warn(
29430
- `[WidgetRegistry] Could not compile ${widgetName}:`,
29431
- compileError,
29432
- );
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.
29433
29436
  }
29434
29437
  }
29435
29438
 
29436
29439
  if (!bundlePath) {
29440
+ const detail = compileError
29441
+ ? ` (auto-compile failed: ${compileError.message})`
29442
+ : "";
29437
29443
  return {
29438
29444
  success: false,
29439
- error: `No bundle found in: ${widget.path}`,
29445
+ error: `No bundle found in: ${widget.path}${detail}`,
29440
29446
  };
29441
29447
  }
29442
29448
 
@@ -64504,6 +64510,74 @@ function stripPersonalizationFromWorkspace$1(workspace) {
64504
64510
  return cleaned;
64505
64511
  }
64506
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
+
64507
64581
  var dashboardConfigUtils$1 = {
64508
64582
  collectComponentNames: collectComponentNames$1,
64509
64583
  collectComponentNamesFromWorkspace: collectComponentNamesFromWorkspace$1,
@@ -64520,6 +64594,7 @@ var dashboardConfigUtils$1 = {
64520
64594
  buildProviderSetupManifest,
64521
64595
  checkApiCompatibility,
64522
64596
  stripPersonalizationFromWorkspace: stripPersonalizationFromWorkspace$1,
64597
+ remapLayoutPackageScopes: remapLayoutPackageScopes$1,
64523
64598
  };
64524
64599
 
64525
64600
  /**
@@ -65561,6 +65636,7 @@ const {
65561
65636
  buildProviderRequirements,
65562
65637
  applyEventWiringToLayout,
65563
65638
  stripPersonalizationFromWorkspace,
65639
+ remapLayoutPackageScopes,
65564
65640
  } = dashboardConfigUtils$1;
65565
65641
  const { searchRegistry, getPackage } = registryController$3;
65566
65642
  const { getStoredToken, clearToken } = registryAuthController$2;
@@ -66980,7 +67056,33 @@ async function prepareDashboardForPublish$1(
66980
67056
  // widget's own `defaultValue` on each field never gets a chance.
66981
67057
  // Layout position, ordering, nested containers, and any title text
66982
67058
  // are preserved (they're part of the template, not personal).
66983
- const sharedWorkspace = stripPersonalizationFromWorkspace(workspace);
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
+ }
66984
67086
  const layout = sharedWorkspace.layout || [];
66985
67087
 
66986
67088
  // 3. Build the dashboard config — walk main + pages + sidebar
@@ -73731,7 +73833,7 @@ const {
73731
73833
  } = registryAuthController$2;
73732
73834
  const widgetRegistryModule = widgetRegistryExports;
73733
73835
  const { dynamicWidgetLoader: dynamicWidgetLoader$1 } = dynamicWidgetLoaderExports;
73734
- const { findWidgetsDir } = widgetCompiler$1;
73836
+ const { findWidgetsDir, compileWidget } = widgetCompiler$1;
73735
73837
  const {
73736
73838
  resolveNextVersion,
73737
73839
  parsePackageName,
@@ -73939,9 +74041,13 @@ async function stageOverrides(srcDir, dstDir, overrides) {
73939
74041
 
73940
74042
  // ─── ZIP builder ─────────────────────────────────────────────────────────────
73941
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.
73942
74049
  const ZIP_EXCLUDE_DIRS = new Set([
73943
74050
  "node_modules",
73944
- "dist",
73945
74051
  ".git",
73946
74052
  ".DS_Store",
73947
74053
  ".next",
@@ -74152,6 +74258,25 @@ async function prepareWidgetForPublish$1(appId, packageId, options = {}) {
74152
74258
  await stageOverrides(widget.path, stagedDir, options.defaultsOverride);
74153
74259
  sourceDir = stagedDir;
74154
74260
  }
74261
+
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
+
74155
74280
  const zip = new AdmZip();
74156
74281
  addDirToZip(zip, sourceDir);
74157
74282
  zip.writeZip(zipPath);