@trops/dash-core 0.1.534 → 0.1.536
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 +135 -0
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -3827,6 +3827,110 @@ var manifestScanner = {
|
|
|
3827
3827
|
SCAN_FILE_LIMIT,
|
|
3828
3828
|
};
|
|
3829
3829
|
|
|
3830
|
+
/**
|
|
3831
|
+
* dedupeWidgetFolders
|
|
3832
|
+
*
|
|
3833
|
+
* Boot-time pass over the widgets cache directory. Looks for
|
|
3834
|
+
* top-level folders that don't follow the canonical `@scope/name`
|
|
3835
|
+
* shape but whose `package.json` declares a scoped name (e.g.
|
|
3836
|
+
* `widgets/pipeline/` containing `{ "name": "@ai-built/pipeline" }`).
|
|
3837
|
+
* These are stale artifacts from older install paths — they coexist
|
|
3838
|
+
* with the canonical `widgets/@scope/name/` folder and crash
|
|
3839
|
+
* ComponentManager with "missing origin metadata" because the
|
|
3840
|
+
* bare-name registry entry has no scope to derive a 3-segment
|
|
3841
|
+
* `<scope>.<package>.<component>` id from.
|
|
3842
|
+
*
|
|
3843
|
+
* Two outcomes per malformed folder:
|
|
3844
|
+
* - Scoped twin already exists → remove the bare copy (redundant)
|
|
3845
|
+
* - Scoped twin missing → move the folder to the canonical
|
|
3846
|
+
* scoped path
|
|
3847
|
+
*
|
|
3848
|
+
* Pure boundary effects (fs read/write/move/remove). The only
|
|
3849
|
+
* registry-side fixup is left to the caller — once this returns,
|
|
3850
|
+
* `widgetRegistry.reconcileWithDisk` re-walks the directory and
|
|
3851
|
+
* picks up the (now canonical) layout cleanly.
|
|
3852
|
+
*
|
|
3853
|
+
* @param {string} widgetsDir
|
|
3854
|
+
* @returns {{removed: string[], migrated: Array<{from: string, to: string}>, errors: Array<{path: string, error: string}>}}
|
|
3855
|
+
*/
|
|
3856
|
+
|
|
3857
|
+
var dedupeWidgetFolders_1;
|
|
3858
|
+
var hasRequiredDedupeWidgetFolders;
|
|
3859
|
+
|
|
3860
|
+
function requireDedupeWidgetFolders () {
|
|
3861
|
+
if (hasRequiredDedupeWidgetFolders) return dedupeWidgetFolders_1;
|
|
3862
|
+
hasRequiredDedupeWidgetFolders = 1;
|
|
3863
|
+
|
|
3864
|
+
const fs = require$$0$2;
|
|
3865
|
+
const path = require$$1$1;
|
|
3866
|
+
|
|
3867
|
+
const RESERVED_TOP_LEVEL = new Set(["registry.json"]);
|
|
3868
|
+
|
|
3869
|
+
function dedupeWidgetFolders(widgetsDir) {
|
|
3870
|
+
const summary = { removed: [], migrated: [], errors: [] };
|
|
3871
|
+
if (typeof widgetsDir !== "string" || !fs.existsSync(widgetsDir)) {
|
|
3872
|
+
return summary;
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
let entries;
|
|
3876
|
+
try {
|
|
3877
|
+
entries = fs.readdirSync(widgetsDir, { withFileTypes: true });
|
|
3878
|
+
} catch (e) {
|
|
3879
|
+
summary.errors.push({ path: widgetsDir, error: e.message });
|
|
3880
|
+
return summary;
|
|
3881
|
+
}
|
|
3882
|
+
|
|
3883
|
+
for (const entry of entries) {
|
|
3884
|
+
if (!entry.isDirectory()) continue;
|
|
3885
|
+
if (RESERVED_TOP_LEVEL.has(entry.name)) continue;
|
|
3886
|
+
// Canonical scoped folders are handled by reconcileWithDisk;
|
|
3887
|
+
// skip them here.
|
|
3888
|
+
if (entry.name.startsWith("@")) continue;
|
|
3889
|
+
|
|
3890
|
+
const bareDir = path.join(widgetsDir, entry.name);
|
|
3891
|
+
const pkgJsonPath = path.join(bareDir, "package.json");
|
|
3892
|
+
if (!fs.existsSync(pkgJsonPath)) continue;
|
|
3893
|
+
|
|
3894
|
+
let pkgName;
|
|
3895
|
+
try {
|
|
3896
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
|
3897
|
+
pkgName = typeof pkg?.name === "string" ? pkg.name : null;
|
|
3898
|
+
} catch (e) {
|
|
3899
|
+
summary.errors.push({ path: bareDir, error: e.message });
|
|
3900
|
+
continue;
|
|
3901
|
+
}
|
|
3902
|
+
|
|
3903
|
+
// Truly unscoped package — leave alone.
|
|
3904
|
+
if (!pkgName || !pkgName.startsWith("@")) continue;
|
|
3905
|
+
|
|
3906
|
+
const parts = pkgName.split("/");
|
|
3907
|
+
if (parts.length !== 2) continue; // malformed scoped name; ignore
|
|
3908
|
+
const scope = parts[0]; // e.g. "@ai-built"
|
|
3909
|
+
const name = parts[1];
|
|
3910
|
+
const scopedDir = path.join(widgetsDir, scope, name);
|
|
3911
|
+
|
|
3912
|
+
try {
|
|
3913
|
+
if (fs.existsSync(scopedDir)) {
|
|
3914
|
+
// Redundant bare copy — remove it.
|
|
3915
|
+
fs.rmSync(bareDir, { recursive: true, force: true });
|
|
3916
|
+
summary.removed.push(bareDir);
|
|
3917
|
+
} else {
|
|
3918
|
+
// Migrate the bare folder to the canonical scoped path.
|
|
3919
|
+
fs.mkdirSync(path.dirname(scopedDir), { recursive: true });
|
|
3920
|
+
fs.renameSync(bareDir, scopedDir);
|
|
3921
|
+
summary.migrated.push({ from: bareDir, to: scopedDir });
|
|
3922
|
+
}
|
|
3923
|
+
} catch (e) {
|
|
3924
|
+
summary.errors.push({ path: bareDir, error: e.message });
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
return summary;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
dedupeWidgetFolders_1 = { dedupeWidgetFolders };
|
|
3931
|
+
return dedupeWidgetFolders_1;
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3830
3934
|
/**
|
|
3831
3935
|
* scanWidgetPackagePermissions
|
|
3832
3936
|
*
|
|
@@ -4847,6 +4951,37 @@ var schedulerController_1 = schedulerController$2;
|
|
|
4847
4951
|
console.error("[WidgetRegistry] Error loading registry:", error);
|
|
4848
4952
|
}
|
|
4849
4953
|
|
|
4954
|
+
// Slice 13f: clean up bare-name folders whose package.json declares
|
|
4955
|
+
// a scoped name (legacy install artifact). Without this, the
|
|
4956
|
+
// `reconcileWithDisk` orphan loop below re-registers them under
|
|
4957
|
+
// the bare folder name and ComponentManager later crashes with
|
|
4958
|
+
// "missing origin metadata" trying to derive a 3-segment id from
|
|
4959
|
+
// a scope-less entry. Runs BEFORE reconcile so the registry's
|
|
4960
|
+
// re-register pass sees a canonical layout.
|
|
4961
|
+
try {
|
|
4962
|
+
const { dedupeWidgetFolders } = requireDedupeWidgetFolders();
|
|
4963
|
+
const dedup = dedupeWidgetFolders(WIDGETS_CACHE_DIR);
|
|
4964
|
+
if (dedup.removed.length > 0 || dedup.migrated.length > 0) {
|
|
4965
|
+
console.log(
|
|
4966
|
+
`[WidgetRegistry] Folder dedupe: removed ${dedup.removed.length}, migrated ${dedup.migrated.length}`,
|
|
4967
|
+
);
|
|
4968
|
+
// Drop any registry entry that pointed at a now-removed bare
|
|
4969
|
+
// folder, so reconcileWithDisk re-registers from the canonical
|
|
4970
|
+
// scoped path on its next pass.
|
|
4971
|
+
const removedSet = new Set(dedup.removed);
|
|
4972
|
+
for (const [key, entry] of Array.from(this.widgets.entries())) {
|
|
4973
|
+
if (entry?.path && removedSet.has(entry.path)) {
|
|
4974
|
+
this.widgets.delete(key);
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
}
|
|
4978
|
+
if (dedup.errors.length > 0) {
|
|
4979
|
+
console.warn(`[WidgetRegistry] Folder dedupe errors:`, dedup.errors);
|
|
4980
|
+
}
|
|
4981
|
+
} catch (e) {
|
|
4982
|
+
console.warn("[WidgetRegistry] Folder dedupe failed:", e.message);
|
|
4983
|
+
}
|
|
4984
|
+
|
|
4850
4985
|
// Reconcile: re-register orphaned widget packages found on disk
|
|
4851
4986
|
this.reconcileWithDisk();
|
|
4852
4987
|
|