@elementspanel/epanel-plugin-instance 1.0.5 → 1.0.7
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/panel/backend/index.cjs
CHANGED
|
@@ -9468,6 +9468,7 @@ Object.defineProperty(exports, "arrayUnique", ({ enumerable: true, get: function
|
|
|
9468
9468
|
__exportStar(__webpack_require__("../common/src/plugin_contract.ts"), exports);
|
|
9469
9469
|
__exportStar(__webpack_require__("../common/src/plugin_overrides.ts"), exports);
|
|
9470
9470
|
__exportStar(__webpack_require__("../common/src/plugin_lifecycle.ts"), exports);
|
|
9471
|
+
__exportStar(__webpack_require__("../common/src/process_restart.ts"), exports);
|
|
9471
9472
|
__exportStar(__webpack_require__("../common/src/plugin_revision.ts"), exports);
|
|
9472
9473
|
__exportStar(__webpack_require__("../common/src/plugin_modules.ts"), exports);
|
|
9473
9474
|
__exportStar(__webpack_require__("../common/src/plugin_watch.ts"), exports);
|
|
@@ -10385,6 +10386,39 @@ async function loadPluginModule(entry, directory, revision) {
|
|
|
10385
10386
|
|
|
10386
10387
|
"use strict";
|
|
10387
10388
|
|
|
10389
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10390
|
+
if (k2 === undefined) k2 = k;
|
|
10391
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10392
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10393
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10394
|
+
}
|
|
10395
|
+
Object.defineProperty(o, k2, desc);
|
|
10396
|
+
}) : (function(o, m, k, k2) {
|
|
10397
|
+
if (k2 === undefined) k2 = k;
|
|
10398
|
+
o[k2] = m[k];
|
|
10399
|
+
}));
|
|
10400
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10401
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
10402
|
+
}) : function(o, v) {
|
|
10403
|
+
o["default"] = v;
|
|
10404
|
+
});
|
|
10405
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
10406
|
+
var ownKeys = function(o) {
|
|
10407
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
10408
|
+
var ar = [];
|
|
10409
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
10410
|
+
return ar;
|
|
10411
|
+
};
|
|
10412
|
+
return ownKeys(o);
|
|
10413
|
+
};
|
|
10414
|
+
return function (mod) {
|
|
10415
|
+
if (mod && mod.__esModule) return mod;
|
|
10416
|
+
var result = {};
|
|
10417
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
10418
|
+
__setModuleDefault(result, mod);
|
|
10419
|
+
return result;
|
|
10420
|
+
};
|
|
10421
|
+
})();
|
|
10388
10422
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10389
10423
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10390
10424
|
};
|
|
@@ -10404,6 +10438,8 @@ const path_1 = __importDefault(__webpack_require__("path"));
|
|
|
10404
10438
|
const module_1 = __webpack_require__("module");
|
|
10405
10439
|
const plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
10406
10440
|
const plugin_contract_1 = __webpack_require__("../common/src/plugin_contract.ts");
|
|
10441
|
+
// @ts-ignore Shared by the source runtime and the published npm launcher.
|
|
10442
|
+
const npmPlugins = __importStar(__webpack_require__("../../scripts/runtime/npm-plugins.cjs"));
|
|
10407
10443
|
const PLUGIN_ID = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
10408
10444
|
const PACKAGE_NAME = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
10409
10445
|
const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/;
|
|
@@ -10445,11 +10481,20 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
|
10445
10481
|
return scope;
|
|
10446
10482
|
}
|
|
10447
10483
|
function npmPluginRoots(options = {}) {
|
|
10448
|
-
var _a, _b;
|
|
10484
|
+
var _a, _b, _c;
|
|
10449
10485
|
const packageRoot = path_1.default.resolve((_a = options.packageRoot) !== null && _a !== void 0 ? _a : currentPackageRoot());
|
|
10486
|
+
const projectRoot = path_1.default.resolve((_b = options.projectRoot) !== null && _b !== void 0 ? _b : currentProjectRoot(packageRoot));
|
|
10487
|
+
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10488
|
+
const side = options.side ||
|
|
10489
|
+
stringValue((_c = objectValue(host === null || host === void 0 ? void 0 : host.elementspanel)) === null || _c === void 0 ? void 0 : _c.side) ||
|
|
10490
|
+
path_1.default.basename(packageRoot);
|
|
10450
10491
|
return {
|
|
10451
10492
|
packageRoot,
|
|
10452
|
-
projectRoot
|
|
10493
|
+
projectRoot,
|
|
10494
|
+
dependencyRoot: path_1.default.dirname(npmPlugins.projectManifestFile(packageRoot, side, {
|
|
10495
|
+
projectRoot,
|
|
10496
|
+
runtimeDirectory: process.env.EPANEL_RUNTIME_ROOT
|
|
10497
|
+
}))
|
|
10453
10498
|
};
|
|
10454
10499
|
}
|
|
10455
10500
|
function projectManifestFile(projectRoot) {
|
|
@@ -10480,15 +10525,10 @@ function pluginRecord(pluginId, name, source, packageRoot, directory, folder, ve
|
|
|
10480
10525
|
function readPackageEntry(packageRoot, name) {
|
|
10481
10526
|
// Read package boundaries directly: Node caches require.resolve() paths even
|
|
10482
10527
|
// after npm moves an installation between nested and hoisted node_modules.
|
|
10483
|
-
|
|
10484
|
-
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
10488
|
-
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
10489
|
-
if (manifestPath)
|
|
10490
|
-
break;
|
|
10491
|
-
}
|
|
10528
|
+
const localRequire = (0, module_1.createRequire)(path_1.default.join(packageRoot, "package.json"));
|
|
10529
|
+
let manifestPath = (localRequire.resolve.paths(name) || [])
|
|
10530
|
+
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
10531
|
+
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
10492
10532
|
if (!manifestPath)
|
|
10493
10533
|
throw new Error(`Missing npm plugin package: ${name}.`);
|
|
10494
10534
|
manifestPath = fs_extra_1.default.realpathSync(manifestPath);
|
|
@@ -10536,84 +10576,26 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
|
|
|
10536
10576
|
/**
|
|
10537
10577
|
* Every npm plugin the runtime can load for a side, built-in and project-installed.
|
|
10538
10578
|
*
|
|
10539
|
-
* Built-in package names
|
|
10540
|
-
*
|
|
10541
|
-
* A project package that does not describe the requested side is skipped instead of failing, which
|
|
10542
|
-
* is what lets a two-sided project share one dependency list between sides.
|
|
10579
|
+
* Built-in package names reserve their plugin ids. The side manifest selects
|
|
10580
|
+
* the installed versions; a package without that side is skipped.
|
|
10543
10581
|
*/
|
|
10544
10582
|
function listNpmPlugins(side, options = {}) {
|
|
10545
|
-
|
|
10546
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10547
|
-
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10548
|
-
if (!host)
|
|
10549
|
-
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
10550
|
-
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
10551
|
-
? null
|
|
10552
|
-
: readProjectManifest(projectRoot);
|
|
10553
|
-
const hostMappings = mappingsOf(host);
|
|
10554
|
-
const projectMappings = { ...mappingsOf(project) };
|
|
10555
|
-
for (const name of Object.keys(dependenciesOf(project))) {
|
|
10556
|
-
if (!PACKAGE_NAME.test(name) || Object.values(projectMappings).includes(name))
|
|
10557
|
-
continue;
|
|
10558
|
-
try {
|
|
10559
|
-
const entry = readPackageEntry(projectRoot, name);
|
|
10560
|
-
const id = stringValue((_a = objectValue(entry.metadata.elementspanel)) === null || _a === void 0 ? void 0 : _a.id);
|
|
10561
|
-
if (PLUGIN_ID.test(id) && projectMappings[id] === undefined)
|
|
10562
|
-
projectMappings[id] = name;
|
|
10563
|
-
}
|
|
10564
|
-
catch (_c) {
|
|
10565
|
-
/* npm may still be writing the package. */
|
|
10566
|
-
}
|
|
10567
|
-
}
|
|
10568
|
-
const mappings = new Map();
|
|
10569
|
-
for (const [pluginId, name] of Object.entries(projectMappings)) {
|
|
10570
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10571
|
-
continue;
|
|
10572
|
-
mappings.set(pluginId, { name, source: "project" });
|
|
10573
|
-
}
|
|
10574
|
-
for (const [pluginId, name] of Object.entries(hostMappings)) {
|
|
10575
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10576
|
-
continue;
|
|
10577
|
-
if (dependenciesOf(host)[name] === undefined)
|
|
10578
|
-
continue;
|
|
10579
|
-
mappings.set(pluginId, {
|
|
10580
|
-
name,
|
|
10581
|
-
source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
|
|
10582
|
-
});
|
|
10583
|
-
}
|
|
10584
|
-
const hostDependencies = dependenciesOf(host);
|
|
10585
|
-
const projectDependencies = dependenciesOf(project);
|
|
10586
|
-
const folders = new Set();
|
|
10583
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots({ ...options, side });
|
|
10587
10584
|
const records = [];
|
|
10588
|
-
for (const
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
entry = readPackageEntry(mapping.source === "project" ? projectRoot : packageRoot, mapping.name);
|
|
10598
|
-
}
|
|
10599
|
-
catch (error) {
|
|
10600
|
-
if (options.skipInvalid)
|
|
10601
|
-
continue;
|
|
10602
|
-
throw error;
|
|
10603
|
-
}
|
|
10604
|
-
const record = recordFromPackage(pluginId, mapping.name, mapping.source, entry.root, entry.metadata, side);
|
|
10585
|
+
for (const item of npmPlugins.resolveNpmPlugins(packageRoot, side, {
|
|
10586
|
+
projectRoot,
|
|
10587
|
+
runtimeDirectory: dependencyRoot,
|
|
10588
|
+
skipInvalid: options.skipInvalid
|
|
10589
|
+
})) {
|
|
10590
|
+
const metadata = readJson(path_1.default.join(item.packageRoot, "package.json"));
|
|
10591
|
+
if (!metadata)
|
|
10592
|
+
continue;
|
|
10593
|
+
const record = recordFromPackage(item.id, item.name, item.source, item.packageRoot, metadata, side);
|
|
10605
10594
|
if (!record) {
|
|
10606
|
-
if (options.skipInvalid || mapping.source === "project")
|
|
10607
|
-
continue;
|
|
10608
|
-
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${mapping.name}.`);
|
|
10609
|
-
}
|
|
10610
|
-
const folder = record.folder;
|
|
10611
|
-
if (folders.has(folder)) {
|
|
10612
10595
|
if (options.skipInvalid)
|
|
10613
10596
|
continue;
|
|
10614
|
-
throw new Error(`
|
|
10597
|
+
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${item.name}.`);
|
|
10615
10598
|
}
|
|
10616
|
-
folders.add(folder);
|
|
10617
10599
|
records.push(record);
|
|
10618
10600
|
}
|
|
10619
10601
|
return records;
|
|
@@ -10712,10 +10694,9 @@ async function acquireProjectLock(projectRoot) {
|
|
|
10712
10694
|
}
|
|
10713
10695
|
}
|
|
10714
10696
|
}
|
|
10715
|
-
function npmPluginOperationPending() {
|
|
10716
|
-
const {
|
|
10717
|
-
return
|
|
10718
|
-
[packageRoot, projectRoot].some((root) => fs_extra_1.default.existsSync(path_1.default.join(root, LOCK_NAME))));
|
|
10697
|
+
function npmPluginOperationPending(side) {
|
|
10698
|
+
const { dependencyRoot } = npmPluginRoots({ side });
|
|
10699
|
+
return operations.size > 0 || fs_extra_1.default.existsSync(path_1.default.join(dependencyRoot, LOCK_NAME));
|
|
10719
10700
|
}
|
|
10720
10701
|
function withProjectLock(projectRoot, operation) {
|
|
10721
10702
|
var _a;
|
|
@@ -10751,19 +10732,16 @@ async function installNpmPlugin(options) {
|
|
|
10751
10732
|
throw new Error(`Invalid plugin id: ${options.pluginId}`);
|
|
10752
10733
|
if (!VERSION.test(version))
|
|
10753
10734
|
throw new Error(`Invalid plugin version: ${version}`);
|
|
10754
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10755
|
-
return withProjectLock(
|
|
10756
|
-
var _a, _b;
|
|
10735
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10736
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10737
|
+
var _a, _b, _c, _d, _e;
|
|
10757
10738
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10758
10739
|
if (!host)
|
|
10759
10740
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
10760
|
-
const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name
|
|
10761
|
-
const targetRoot =
|
|
10762
|
-
? packageRoot
|
|
10763
|
-
: projectRoot;
|
|
10741
|
+
const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name)) === null || _a === void 0 ? void 0 : _a[0];
|
|
10742
|
+
const targetRoot = dependencyRoot;
|
|
10764
10743
|
if (options.pluginId &&
|
|
10765
10744
|
mappingsOf(host)[options.pluginId] &&
|
|
10766
|
-
dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
|
|
10767
10745
|
mappingsOf(host)[options.pluginId] !== name)
|
|
10768
10746
|
throw new Error(`BUNDLED:${options.pluginId}`);
|
|
10769
10747
|
const original = readProjectManifest(targetRoot);
|
|
@@ -10773,7 +10751,7 @@ async function installNpmPlugin(options) {
|
|
|
10773
10751
|
try {
|
|
10774
10752
|
previousVersion = readPackageEntry(targetRoot, name).metadata.version || previous;
|
|
10775
10753
|
}
|
|
10776
|
-
catch (
|
|
10754
|
+
catch (_f) {
|
|
10777
10755
|
/* Keep the declared spec if the previous package is incomplete. */
|
|
10778
10756
|
}
|
|
10779
10757
|
}
|
|
@@ -10792,24 +10770,32 @@ async function installNpmPlugin(options) {
|
|
|
10792
10770
|
"--save-exact",
|
|
10793
10771
|
"--no-fund",
|
|
10794
10772
|
"--no-audit",
|
|
10795
|
-
"--ignore-scripts"
|
|
10773
|
+
"--ignore-scripts",
|
|
10774
|
+
"--workspaces=false"
|
|
10796
10775
|
], targetRoot);
|
|
10797
10776
|
const entry = readPackageEntry(targetRoot, name);
|
|
10798
10777
|
const pluginId = options.pluginId || stringValue((_b = objectValue(entry.metadata.elementspanel)) === null || _b === void 0 ? void 0 : _b.id);
|
|
10799
10778
|
if (!PLUGIN_ID.test(pluginId))
|
|
10800
10779
|
throw new Error(`Invalid plugin id in ${name}.`);
|
|
10801
|
-
if (mappingsOf(host)[pluginId] &&
|
|
10802
|
-
dependenciesOf(host)[String(mappingsOf(host)[pluginId])] !== undefined &&
|
|
10803
|
-
mappingsOf(host)[pluginId] !== name)
|
|
10780
|
+
if (mappingsOf(host)[pluginId] && mappingsOf(host)[pluginId] !== name)
|
|
10804
10781
|
throw new Error(`Plugin id ${pluginId} belongs to a bundled dependency.`);
|
|
10805
10782
|
if (hostId && pluginId !== hostId)
|
|
10806
10783
|
throw new Error(`The package ${name} changed its plugin id from ${hostId} to ${pluginId}.`);
|
|
10807
10784
|
const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
|
|
10808
10785
|
if (mapped !== undefined && mapped !== name)
|
|
10809
10786
|
throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
|
|
10810
|
-
const record = recordFromPackage(pluginId, name,
|
|
10787
|
+
const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
|
|
10811
10788
|
if (!record)
|
|
10812
10789
|
throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
|
|
10790
|
+
if (side === "panel") {
|
|
10791
|
+
const expected = (_d = objectValue((_c = objectValue(entry.metadata.elementspanel)) === null || _c === void 0 ? void 0 : _c.panel)) === null || _d === void 0 ? void 0 : _d.frontendAssets;
|
|
10792
|
+
const available = (_e = objectValue(host.elementspanel)) === null || _e === void 0 ? void 0 : _e.frontendAssets;
|
|
10793
|
+
if ((hostId || expected !== undefined) &&
|
|
10794
|
+
(!Array.isArray(expected) ||
|
|
10795
|
+
!Array.isArray(available) ||
|
|
10796
|
+
expected.some((file) => typeof file !== "string" || !available.includes(file))))
|
|
10797
|
+
throw new Error(`Frontend assets in ${name} do not match this panel. Update the panel or install a matching plugin version.`);
|
|
10798
|
+
}
|
|
10813
10799
|
if (/^[0-9]/.test(version) && record.version !== version)
|
|
10814
10800
|
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
10815
10801
|
if (!process.env.EPANEL_PACKAGE_ROOT &&
|
|
@@ -10853,7 +10839,8 @@ async function installNpmPlugin(options) {
|
|
|
10853
10839
|
"--save",
|
|
10854
10840
|
"--no-fund",
|
|
10855
10841
|
"--no-audit",
|
|
10856
|
-
"--ignore-scripts"
|
|
10842
|
+
"--ignore-scripts",
|
|
10843
|
+
"--workspaces=false"
|
|
10857
10844
|
]
|
|
10858
10845
|
: [
|
|
10859
10846
|
"--prefix",
|
|
@@ -10862,7 +10849,8 @@ async function installNpmPlugin(options) {
|
|
|
10862
10849
|
name,
|
|
10863
10850
|
"--no-fund",
|
|
10864
10851
|
"--no-audit",
|
|
10865
|
-
"--ignore-scripts"
|
|
10852
|
+
"--ignore-scripts",
|
|
10853
|
+
"--workspaces=false"
|
|
10866
10854
|
], targetRoot);
|
|
10867
10855
|
}
|
|
10868
10856
|
catch (rollback) {
|
|
@@ -10886,22 +10874,29 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
|
10886
10874
|
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
10887
10875
|
if (isEssentialNpmPlugin(pluginId))
|
|
10888
10876
|
throw new Error(`The essential plugin "${pluginId}" cannot be uninstalled.`);
|
|
10889
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10890
|
-
return withProjectLock(
|
|
10877
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10878
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10891
10879
|
var _a, _b;
|
|
10892
|
-
const
|
|
10893
|
-
const bundledName = mappingsOf(host)[pluginId];
|
|
10894
|
-
const targetRoot = typeof bundledName === "string" &&
|
|
10895
|
-
dependenciesOf(host)[bundledName] !== undefined &&
|
|
10896
|
-
dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
|
|
10897
|
-
? packageRoot
|
|
10898
|
-
: projectRoot;
|
|
10880
|
+
const targetRoot = dependencyRoot;
|
|
10899
10881
|
const manifest = readProjectManifest(targetRoot);
|
|
10900
|
-
const name = (_a = mappingsOf(manifest)[pluginId]) !== null && _a !== void 0 ? _a : (_b = listNpmPlugins(
|
|
10882
|
+
const name = (_a = mappingsOf(manifest)[pluginId]) !== null && _a !== void 0 ? _a : (_b = listNpmPlugins(options.side, { packageRoot, projectRoot, skipInvalid: true }).find((item) => item.pluginId === pluginId)) === null || _b === void 0 ? void 0 : _b.name;
|
|
10901
10883
|
if (typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10902
10884
|
return null;
|
|
10903
|
-
const record = listNpmPlugins(
|
|
10904
|
-
|
|
10885
|
+
const record = listNpmPlugins(options.side, {
|
|
10886
|
+
packageRoot,
|
|
10887
|
+
projectRoot,
|
|
10888
|
+
skipInvalid: true
|
|
10889
|
+
}).find((item) => item.pluginId === pluginId);
|
|
10890
|
+
await runNpm([
|
|
10891
|
+
"--prefix",
|
|
10892
|
+
targetRoot,
|
|
10893
|
+
"uninstall",
|
|
10894
|
+
name,
|
|
10895
|
+
"--no-fund",
|
|
10896
|
+
"--no-audit",
|
|
10897
|
+
"--ignore-scripts",
|
|
10898
|
+
"--workspaces=false"
|
|
10899
|
+
], targetRoot);
|
|
10905
10900
|
const updated = readProjectManifest(targetRoot);
|
|
10906
10901
|
const plugins = { ...mappingsOf(updated) };
|
|
10907
10902
|
delete plugins[pluginId];
|
|
@@ -11075,11 +11070,11 @@ const plugin_npm_1 = __webpack_require__("../common/src/plugin_npm.ts");
|
|
|
11075
11070
|
/** Poll package boundaries, allowing npm to finish replacing files before reconciliation. */
|
|
11076
11071
|
function watchNpmPlugins(ctx, side, reload, changed) {
|
|
11077
11072
|
const stamp = () => {
|
|
11078
|
-
const { packageRoot,
|
|
11073
|
+
const { packageRoot, dependencyRoot } = (0, plugin_npm_1.npmPluginRoots)({ side });
|
|
11079
11074
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(packageRoot, "package.json")))
|
|
11080
11075
|
return "";
|
|
11081
11076
|
const files = [];
|
|
11082
|
-
for (const root of [packageRoot,
|
|
11077
|
+
for (const root of [packageRoot, dependencyRoot])
|
|
11083
11078
|
for (const name of [
|
|
11084
11079
|
"package.json",
|
|
11085
11080
|
"package-lock.json",
|
|
@@ -11103,7 +11098,7 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
11103
11098
|
let candidate = applied;
|
|
11104
11099
|
let busy = false;
|
|
11105
11100
|
ctx.setInterval(() => {
|
|
11106
|
-
if (busy || (0, plugin_npm_1.npmPluginOperationPending)())
|
|
11101
|
+
if (busy || (0, plugin_npm_1.npmPluginOperationPending)(side))
|
|
11107
11102
|
return;
|
|
11108
11103
|
try {
|
|
11109
11104
|
const next = stamp();
|
|
@@ -11134,6 +11129,51 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
11134
11129
|
}
|
|
11135
11130
|
|
|
11136
11131
|
|
|
11132
|
+
/***/ },
|
|
11133
|
+
|
|
11134
|
+
/***/ "../common/src/process_restart.ts"
|
|
11135
|
+
(__unused_webpack_module, exports) {
|
|
11136
|
+
|
|
11137
|
+
"use strict";
|
|
11138
|
+
|
|
11139
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
11140
|
+
exports.isProcessRestartPending = isProcessRestartPending;
|
|
11141
|
+
exports.requestProcessRestart = requestProcessRestart;
|
|
11142
|
+
const RESTART = Symbol.for("elementspanel.process.restart");
|
|
11143
|
+
function isProcessRestartPending(ctx) {
|
|
11144
|
+
var _a;
|
|
11145
|
+
return ((_a = ctx.root[RESTART]) === null || _a === void 0 ? void 0 : _a.pending) === true;
|
|
11146
|
+
}
|
|
11147
|
+
/** The CLI retains instance processes and starts a fresh worker after this one exits. */
|
|
11148
|
+
function requestProcessRestart(ctx, settle, ready = async () => { }) {
|
|
11149
|
+
if (isProcessRestartPending(ctx))
|
|
11150
|
+
return true;
|
|
11151
|
+
if (process.env.EPANEL_SUPERVISED !== "1" || !process.connected || !process.send)
|
|
11152
|
+
return false;
|
|
11153
|
+
const state = { pending: true };
|
|
11154
|
+
ctx.root[RESTART] = state;
|
|
11155
|
+
const retainProcesses = () => new Promise((resolve, reject) => process.send({ type: "elementspanel:prepare-restart" }, (error) => error ? reject(error) : resolve()));
|
|
11156
|
+
setImmediate(() => {
|
|
11157
|
+
void (async () => {
|
|
11158
|
+
await ready();
|
|
11159
|
+
// Detach output consumers before cleanup so output and exits during the
|
|
11160
|
+
// restart are retained for the next daemon generation.
|
|
11161
|
+
await retainProcesses();
|
|
11162
|
+
await ctx.parallel("process/restarting");
|
|
11163
|
+
// A pending start can finish while restart hooks are awaiting it.
|
|
11164
|
+
await retainProcesses();
|
|
11165
|
+
await ctx.stop();
|
|
11166
|
+
await settle();
|
|
11167
|
+
process.send({ type: "elementspanel:restart" }, (error) => process.exit(error ? 1 : 0));
|
|
11168
|
+
})().catch((error) => {
|
|
11169
|
+
ctx.logger.error("Failed to restart the process:", error);
|
|
11170
|
+
process.exit(1);
|
|
11171
|
+
});
|
|
11172
|
+
});
|
|
11173
|
+
return true;
|
|
11174
|
+
}
|
|
11175
|
+
|
|
11176
|
+
|
|
11137
11177
|
/***/ },
|
|
11138
11178
|
|
|
11139
11179
|
/***/ "../common/src/process_tools.ts"
|
|
@@ -12081,6 +12121,226 @@ module.exports = require("util");
|
|
|
12081
12121
|
"use strict";
|
|
12082
12122
|
module.exports = require("zlib");
|
|
12083
12123
|
|
|
12124
|
+
/***/ },
|
|
12125
|
+
|
|
12126
|
+
/***/ "../../scripts/runtime/npm-plugins.cjs"
|
|
12127
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
12128
|
+
|
|
12129
|
+
const fs = __webpack_require__("node:fs");
|
|
12130
|
+
const path = __webpack_require__("node:path");
|
|
12131
|
+
const { createRequire } = __webpack_require__("node:module");
|
|
12132
|
+
|
|
12133
|
+
const readJson = (filename) => JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
12134
|
+
const readOptional = (filename) => {
|
|
12135
|
+
try {
|
|
12136
|
+
return readJson(filename);
|
|
12137
|
+
} catch (error) {
|
|
12138
|
+
if (error.code === "ENOENT") return null;
|
|
12139
|
+
throw error;
|
|
12140
|
+
}
|
|
12141
|
+
};
|
|
12142
|
+
const validId = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
12143
|
+
const validName = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
12144
|
+
|
|
12145
|
+
function packageManifest(root, name) {
|
|
12146
|
+
const localRequire = createRequire(path.join(root, "package.json"));
|
|
12147
|
+
const filename = (localRequire.resolve.paths(name) || [])
|
|
12148
|
+
.map((directory) => path.join(directory, name, "package.json"))
|
|
12149
|
+
.find((candidate) => fs.existsSync(candidate));
|
|
12150
|
+
if (!filename) throw new Error(`Missing npm package: ${name}`);
|
|
12151
|
+
return fs.realpathSync(filename);
|
|
12152
|
+
}
|
|
12153
|
+
|
|
12154
|
+
function within(root, filename) {
|
|
12155
|
+
const relative = path.relative(root, filename);
|
|
12156
|
+
return (
|
|
12157
|
+
relative === "" ||
|
|
12158
|
+
(relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))
|
|
12159
|
+
);
|
|
12160
|
+
}
|
|
12161
|
+
|
|
12162
|
+
function projectRoot(packageRoot) {
|
|
12163
|
+
if (process.env.EPANEL_PROJECT_ROOT) return path.resolve(process.env.EPANEL_PROJECT_ROOT);
|
|
12164
|
+
const parent = path.resolve(packageRoot, "..");
|
|
12165
|
+
if (path.basename(parent) === "core") return path.dirname(parent);
|
|
12166
|
+
// An installed runtime sits at <project>/node_modules/@scope/<side>; the
|
|
12167
|
+
// project itself is three levels above the package. A development checkout
|
|
12168
|
+
// sits below core/ and is handled above.
|
|
12169
|
+
const scope = parent;
|
|
12170
|
+
const nodeModules = path.dirname(scope);
|
|
12171
|
+
if (path.basename(nodeModules) === "node_modules" && path.basename(scope).startsWith("@")) {
|
|
12172
|
+
return path.dirname(nodeModules);
|
|
12173
|
+
}
|
|
12174
|
+
return parent;
|
|
12175
|
+
}
|
|
12176
|
+
|
|
12177
|
+
function projectManifestFile(packageRoot, side, options = {}) {
|
|
12178
|
+
const selectedSide =
|
|
12179
|
+
side ||
|
|
12180
|
+
readJson(path.join(packageRoot, "package.json")).elementspanel?.side ||
|
|
12181
|
+
path.basename(packageRoot);
|
|
12182
|
+
if (!["panel", "daemon"].includes(selectedSide)) throw new Error("Missing runtime side.");
|
|
12183
|
+
const directory =
|
|
12184
|
+
options.runtimeDirectory ||
|
|
12185
|
+
(!options.projectRoot && process.env.EPANEL_RUNTIME_ROOT) ||
|
|
12186
|
+
path.join(options.projectRoot || projectRoot(packageRoot), selectedSide);
|
|
12187
|
+
return path.join(path.resolve(directory), "package.json");
|
|
12188
|
+
}
|
|
12189
|
+
|
|
12190
|
+
function mappingOf(manifest) {
|
|
12191
|
+
const plugins = manifest?.elementspanel?.plugins;
|
|
12192
|
+
return plugins && typeof plugins === "object" && !Array.isArray(plugins) ? plugins : {};
|
|
12193
|
+
}
|
|
12194
|
+
|
|
12195
|
+
function dependenciesOf(manifest) {
|
|
12196
|
+
const dependencies = manifest?.dependencies;
|
|
12197
|
+
return dependencies && typeof dependencies === "object" ? dependencies : {};
|
|
12198
|
+
}
|
|
12199
|
+
|
|
12200
|
+
/**
|
|
12201
|
+
* Resolve plugins declared in the side's package.json, including hoisted npm
|
|
12202
|
+
* installations. The host catalogue reserves built-in ids without owning their
|
|
12203
|
+
* versions. Other explicitly mapped plugins remain dormant until enabled.
|
|
12204
|
+
* Runtime startup passes skipInvalid so an optional package being removed does
|
|
12205
|
+
* not stop the host; the caller separately validates the small set of core
|
|
12206
|
+
* plugins.
|
|
12207
|
+
*/
|
|
12208
|
+
function resolveNpmPlugins(packageRoot, side, options = {}) {
|
|
12209
|
+
const skipInvalid = options.skipInvalid === true;
|
|
12210
|
+
const host = readJson(path.join(packageRoot, "package.json"));
|
|
12211
|
+
const selectedSide = side || host.elementspanel?.side || path.basename(packageRoot);
|
|
12212
|
+
const projectFile = projectManifestFile(packageRoot, selectedSide, options);
|
|
12213
|
+
const project = readOptional(projectFile);
|
|
12214
|
+
const dependencyRoot = path.dirname(projectFile);
|
|
12215
|
+
|
|
12216
|
+
// The side manifest owns every dependency; the host only reserves identities.
|
|
12217
|
+
const configured = new Map();
|
|
12218
|
+
for (const [id, name] of Object.entries(mappingOf(project)))
|
|
12219
|
+
configured.set(id, { name, source: "project" });
|
|
12220
|
+
for (const name of Object.keys(dependenciesOf(project))) {
|
|
12221
|
+
if (!validName.test(name) || [...configured.values()].some((item) => item.name === name))
|
|
12222
|
+
continue;
|
|
12223
|
+
try {
|
|
12224
|
+
const metadata = readJson(packageManifest(dependencyRoot, name));
|
|
12225
|
+
const id = metadata.elementspanel?.id;
|
|
12226
|
+
if (validId.test(id) && !configured.has(id))
|
|
12227
|
+
configured.set(id, { name, source: "project", automatic: true });
|
|
12228
|
+
} catch {
|
|
12229
|
+
/* Ignore incomplete npm installations until the next scan. */
|
|
12230
|
+
}
|
|
12231
|
+
}
|
|
12232
|
+
for (const [id, name] of Object.entries(mappingOf(host))) {
|
|
12233
|
+
if (dependenciesOf(project)[name] !== undefined)
|
|
12234
|
+
configured.set(id, {
|
|
12235
|
+
name,
|
|
12236
|
+
source: "bundled",
|
|
12237
|
+
automatic: true
|
|
12238
|
+
});
|
|
12239
|
+
else if (configured.has(id)) {
|
|
12240
|
+
if (!skipInvalid) throw new Error(`Plugin id ${id} belongs to built-in package ${name}.`);
|
|
12241
|
+
configured.delete(id);
|
|
12242
|
+
}
|
|
12243
|
+
}
|
|
12244
|
+
|
|
12245
|
+
const projectDependencies = dependenciesOf(project);
|
|
12246
|
+
const folders = new Set();
|
|
12247
|
+
const records = [];
|
|
12248
|
+
|
|
12249
|
+
for (const [id, mapping] of configured) {
|
|
12250
|
+
const name = mapping.name;
|
|
12251
|
+
if (
|
|
12252
|
+
!validId.test(id) ||
|
|
12253
|
+
typeof name !== "string" ||
|
|
12254
|
+
!validName.test(name) ||
|
|
12255
|
+
projectDependencies[name] === undefined
|
|
12256
|
+
) {
|
|
12257
|
+
if (skipInvalid) continue;
|
|
12258
|
+
throw new Error(`Invalid npm plugin dependency: ${id}.`);
|
|
12259
|
+
}
|
|
12260
|
+
|
|
12261
|
+
let manifestPath;
|
|
12262
|
+
let failure;
|
|
12263
|
+
try {
|
|
12264
|
+
manifestPath = packageManifest(dependencyRoot, name);
|
|
12265
|
+
} catch (error) {
|
|
12266
|
+
failure = error;
|
|
12267
|
+
}
|
|
12268
|
+
if (!manifestPath) {
|
|
12269
|
+
if (skipInvalid) continue;
|
|
12270
|
+
throw new Error(`Missing npm plugin ${name}. Run npm install in ${dependencyRoot}.`, {
|
|
12271
|
+
cause: failure
|
|
12272
|
+
});
|
|
12273
|
+
}
|
|
12274
|
+
let metadata;
|
|
12275
|
+
try {
|
|
12276
|
+
metadata = readJson(manifestPath);
|
|
12277
|
+
} catch (error) {
|
|
12278
|
+
if (skipInvalid) continue;
|
|
12279
|
+
throw error;
|
|
12280
|
+
}
|
|
12281
|
+
const definition = metadata.elementspanel?.[selectedSide];
|
|
12282
|
+
// A project dependency may only ship one side; the other side simply does
|
|
12283
|
+
// not see it. A built-in plugin declared by the runtime must carry this side.
|
|
12284
|
+
if (!definition) {
|
|
12285
|
+
if (mapping.source === "project" || skipInvalid) continue;
|
|
12286
|
+
throw new Error(`Invalid ${selectedSide} entry in npm plugin ${name}.`);
|
|
12287
|
+
}
|
|
12288
|
+
const pluginRoot = path.dirname(manifestPath);
|
|
12289
|
+
if (
|
|
12290
|
+
typeof definition.directory !== "string" ||
|
|
12291
|
+
typeof definition.folder !== "string" ||
|
|
12292
|
+
!validId.test(definition.folder) ||
|
|
12293
|
+
path.isAbsolute(definition.directory)
|
|
12294
|
+
) {
|
|
12295
|
+
if (skipInvalid) continue;
|
|
12296
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
12297
|
+
}
|
|
12298
|
+
const directory = path.resolve(pluginRoot, definition.directory);
|
|
12299
|
+
if (directory === pluginRoot || !within(pluginRoot, directory)) {
|
|
12300
|
+
if (skipInvalid) continue;
|
|
12301
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
12302
|
+
}
|
|
12303
|
+
let entries;
|
|
12304
|
+
try {
|
|
12305
|
+
entries = readJson(path.join(directory, "plugin.json"));
|
|
12306
|
+
} catch (error) {
|
|
12307
|
+
if (skipInvalid) continue;
|
|
12308
|
+
throw error;
|
|
12309
|
+
}
|
|
12310
|
+
if (
|
|
12311
|
+
metadata.elementspanel?.id !== id ||
|
|
12312
|
+
typeof metadata.version !== "string" ||
|
|
12313
|
+
!metadata.version.trim() ||
|
|
12314
|
+
!entries ||
|
|
12315
|
+
typeof entries !== "object" ||
|
|
12316
|
+
Array.isArray(entries)
|
|
12317
|
+
) {
|
|
12318
|
+
if (skipInvalid) continue;
|
|
12319
|
+
throw new Error(`Invalid npm plugin identity or version in package.json: ${name}.`);
|
|
12320
|
+
}
|
|
12321
|
+
if (folders.has(definition.folder)) {
|
|
12322
|
+
if (skipInvalid) continue;
|
|
12323
|
+
throw new Error(`Duplicate npm plugin asset directory: ${definition.folder}.`);
|
|
12324
|
+
}
|
|
12325
|
+
folders.add(definition.folder);
|
|
12326
|
+
records.push({
|
|
12327
|
+
id,
|
|
12328
|
+
name,
|
|
12329
|
+
version: metadata.version,
|
|
12330
|
+
source: mapping.source,
|
|
12331
|
+
defaultEnabled: mapping.automatic === true || mapping.source !== "project",
|
|
12332
|
+
packageRoot: pluginRoot,
|
|
12333
|
+
directory,
|
|
12334
|
+
folder: definition.folder,
|
|
12335
|
+
dependencies: Object.keys(metadata.dependencies || {})
|
|
12336
|
+
});
|
|
12337
|
+
}
|
|
12338
|
+
return records;
|
|
12339
|
+
}
|
|
12340
|
+
|
|
12341
|
+
module.exports = { resolveNpmPlugins, projectManifestFile };
|
|
12342
|
+
|
|
12343
|
+
|
|
12084
12344
|
/***/ },
|
|
12085
12345
|
|
|
12086
12346
|
/***/ "../../scripts/workspace-layout.cjs"
|