@elementspanel/epanel-plugin-instance 1.0.6 → 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/daemon/backend/index.cjs +329 -113
- package/package.json +42 -4
- package/panel/backend/index.cjs +331 -117
package/daemon/backend/index.cjs
CHANGED
|
@@ -9668,6 +9668,39 @@ async function loadPluginModule(entry, directory, revision) {
|
|
|
9668
9668
|
|
|
9669
9669
|
"use strict";
|
|
9670
9670
|
|
|
9671
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9672
|
+
if (k2 === undefined) k2 = k;
|
|
9673
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9674
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9675
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9676
|
+
}
|
|
9677
|
+
Object.defineProperty(o, k2, desc);
|
|
9678
|
+
}) : (function(o, m, k, k2) {
|
|
9679
|
+
if (k2 === undefined) k2 = k;
|
|
9680
|
+
o[k2] = m[k];
|
|
9681
|
+
}));
|
|
9682
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
9683
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
9684
|
+
}) : function(o, v) {
|
|
9685
|
+
o["default"] = v;
|
|
9686
|
+
});
|
|
9687
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
9688
|
+
var ownKeys = function(o) {
|
|
9689
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
9690
|
+
var ar = [];
|
|
9691
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
9692
|
+
return ar;
|
|
9693
|
+
};
|
|
9694
|
+
return ownKeys(o);
|
|
9695
|
+
};
|
|
9696
|
+
return function (mod) {
|
|
9697
|
+
if (mod && mod.__esModule) return mod;
|
|
9698
|
+
var result = {};
|
|
9699
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
9700
|
+
__setModuleDefault(result, mod);
|
|
9701
|
+
return result;
|
|
9702
|
+
};
|
|
9703
|
+
})();
|
|
9671
9704
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9672
9705
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9673
9706
|
};
|
|
@@ -9686,6 +9719,8 @@ const path_1 = __importDefault(__webpack_require__("path"));
|
|
|
9686
9719
|
const module_1 = __webpack_require__("module");
|
|
9687
9720
|
const plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
9688
9721
|
const plugin_contract_1 = __webpack_require__("../common/src/plugin_contract.ts");
|
|
9722
|
+
// @ts-ignore Shared by the source runtime and the published npm launcher.
|
|
9723
|
+
const npmPlugins = __importStar(__webpack_require__("../../scripts/runtime/npm-plugins.cjs"));
|
|
9689
9724
|
const PLUGIN_ID = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
9690
9725
|
const PACKAGE_NAME = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
9691
9726
|
const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/;
|
|
@@ -9728,9 +9763,18 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
|
9728
9763
|
}
|
|
9729
9764
|
function npmPluginRoots(options = {}) {
|
|
9730
9765
|
const packageRoot = path_1.default.resolve(options.packageRoot ?? currentPackageRoot());
|
|
9766
|
+
const projectRoot = path_1.default.resolve(options.projectRoot ?? currentProjectRoot(packageRoot));
|
|
9767
|
+
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
9768
|
+
const side = options.side ||
|
|
9769
|
+
stringValue(objectValue(host?.elementspanel)?.side) ||
|
|
9770
|
+
path_1.default.basename(packageRoot);
|
|
9731
9771
|
return {
|
|
9732
9772
|
packageRoot,
|
|
9733
|
-
projectRoot
|
|
9773
|
+
projectRoot,
|
|
9774
|
+
dependencyRoot: path_1.default.dirname(npmPlugins.projectManifestFile(packageRoot, side, {
|
|
9775
|
+
projectRoot,
|
|
9776
|
+
runtimeDirectory: process.env.EPANEL_RUNTIME_ROOT
|
|
9777
|
+
}))
|
|
9734
9778
|
};
|
|
9735
9779
|
}
|
|
9736
9780
|
function projectManifestFile(projectRoot) {
|
|
@@ -9758,15 +9802,10 @@ function pluginRecord(pluginId, name, source, packageRoot, directory, folder, ve
|
|
|
9758
9802
|
function readPackageEntry(packageRoot, name) {
|
|
9759
9803
|
// Read package boundaries directly: Node caches require.resolve() paths even
|
|
9760
9804
|
// after npm moves an installation between nested and hoisted node_modules.
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
9766
|
-
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
9767
|
-
if (manifestPath)
|
|
9768
|
-
break;
|
|
9769
|
-
}
|
|
9805
|
+
const localRequire = (0, module_1.createRequire)(path_1.default.join(packageRoot, "package.json"));
|
|
9806
|
+
let manifestPath = (localRequire.resolve.paths(name) || [])
|
|
9807
|
+
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
9808
|
+
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
9770
9809
|
if (!manifestPath)
|
|
9771
9810
|
throw new Error(`Missing npm plugin package: ${name}.`);
|
|
9772
9811
|
manifestPath = fs_extra_1.default.realpathSync(manifestPath);
|
|
@@ -9813,83 +9852,26 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
|
|
|
9813
9852
|
/**
|
|
9814
9853
|
* Every npm plugin the runtime can load for a side, built-in and project-installed.
|
|
9815
9854
|
*
|
|
9816
|
-
* Built-in package names
|
|
9817
|
-
*
|
|
9818
|
-
* A project package that does not describe the requested side is skipped instead of failing, which
|
|
9819
|
-
* is what lets a two-sided project share one dependency list between sides.
|
|
9855
|
+
* Built-in package names reserve their plugin ids. The side manifest selects
|
|
9856
|
+
* the installed versions; a package without that side is skipped.
|
|
9820
9857
|
*/
|
|
9821
9858
|
function listNpmPlugins(side, options = {}) {
|
|
9822
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
9823
|
-
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
9824
|
-
if (!host)
|
|
9825
|
-
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
9826
|
-
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
9827
|
-
? null
|
|
9828
|
-
: readProjectManifest(projectRoot);
|
|
9829
|
-
const hostMappings = mappingsOf(host);
|
|
9830
|
-
const projectMappings = { ...mappingsOf(project) };
|
|
9831
|
-
for (const name of Object.keys(dependenciesOf(project))) {
|
|
9832
|
-
if (!PACKAGE_NAME.test(name) || Object.values(projectMappings).includes(name))
|
|
9833
|
-
continue;
|
|
9834
|
-
try {
|
|
9835
|
-
const entry = readPackageEntry(projectRoot, name);
|
|
9836
|
-
const id = stringValue(objectValue(entry.metadata.elementspanel)?.id);
|
|
9837
|
-
if (PLUGIN_ID.test(id) && projectMappings[id] === undefined)
|
|
9838
|
-
projectMappings[id] = name;
|
|
9839
|
-
}
|
|
9840
|
-
catch {
|
|
9841
|
-
/* npm may still be writing the package. */
|
|
9842
|
-
}
|
|
9843
|
-
}
|
|
9844
|
-
const mappings = new Map();
|
|
9845
|
-
for (const [pluginId, name] of Object.entries(projectMappings)) {
|
|
9846
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
9847
|
-
continue;
|
|
9848
|
-
mappings.set(pluginId, { name, source: "project" });
|
|
9849
|
-
}
|
|
9850
|
-
for (const [pluginId, name] of Object.entries(hostMappings)) {
|
|
9851
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
9852
|
-
continue;
|
|
9853
|
-
if (dependenciesOf(host)[name] === undefined)
|
|
9854
|
-
continue;
|
|
9855
|
-
mappings.set(pluginId, {
|
|
9856
|
-
name,
|
|
9857
|
-
source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
|
|
9858
|
-
});
|
|
9859
|
-
}
|
|
9860
|
-
const hostDependencies = dependenciesOf(host);
|
|
9861
|
-
const projectDependencies = dependenciesOf(project);
|
|
9862
|
-
const folders = new Set();
|
|
9859
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots({ ...options, side });
|
|
9863
9860
|
const records = [];
|
|
9864
|
-
for (const
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
entry = readPackageEntry(mapping.source === "project" ? projectRoot : packageRoot, mapping.name);
|
|
9874
|
-
}
|
|
9875
|
-
catch (error) {
|
|
9876
|
-
if (options.skipInvalid)
|
|
9877
|
-
continue;
|
|
9878
|
-
throw error;
|
|
9879
|
-
}
|
|
9880
|
-
const record = recordFromPackage(pluginId, mapping.name, mapping.source, entry.root, entry.metadata, side);
|
|
9861
|
+
for (const item of npmPlugins.resolveNpmPlugins(packageRoot, side, {
|
|
9862
|
+
projectRoot,
|
|
9863
|
+
runtimeDirectory: dependencyRoot,
|
|
9864
|
+
skipInvalid: options.skipInvalid
|
|
9865
|
+
})) {
|
|
9866
|
+
const metadata = readJson(path_1.default.join(item.packageRoot, "package.json"));
|
|
9867
|
+
if (!metadata)
|
|
9868
|
+
continue;
|
|
9869
|
+
const record = recordFromPackage(item.id, item.name, item.source, item.packageRoot, metadata, side);
|
|
9881
9870
|
if (!record) {
|
|
9882
|
-
if (options.skipInvalid || mapping.source === "project")
|
|
9883
|
-
continue;
|
|
9884
|
-
throw new Error(`Invalid ${side ?? "plugin"} entry in npm plugin ${mapping.name}.`);
|
|
9885
|
-
}
|
|
9886
|
-
const folder = record.folder;
|
|
9887
|
-
if (folders.has(folder)) {
|
|
9888
9871
|
if (options.skipInvalid)
|
|
9889
9872
|
continue;
|
|
9890
|
-
throw new Error(`
|
|
9873
|
+
throw new Error(`Invalid ${side ?? "plugin"} entry in npm plugin ${item.name}.`);
|
|
9891
9874
|
}
|
|
9892
|
-
folders.add(folder);
|
|
9893
9875
|
records.push(record);
|
|
9894
9876
|
}
|
|
9895
9877
|
return records;
|
|
@@ -9986,10 +9968,9 @@ async function acquireProjectLock(projectRoot) {
|
|
|
9986
9968
|
}
|
|
9987
9969
|
}
|
|
9988
9970
|
}
|
|
9989
|
-
function npmPluginOperationPending() {
|
|
9990
|
-
const {
|
|
9991
|
-
return
|
|
9992
|
-
[packageRoot, projectRoot].some((root) => fs_extra_1.default.existsSync(path_1.default.join(root, LOCK_NAME))));
|
|
9971
|
+
function npmPluginOperationPending(side) {
|
|
9972
|
+
const { dependencyRoot } = npmPluginRoots({ side });
|
|
9973
|
+
return operations.size > 0 || fs_extra_1.default.existsSync(path_1.default.join(dependencyRoot, LOCK_NAME));
|
|
9993
9974
|
}
|
|
9994
9975
|
function withProjectLock(projectRoot, operation) {
|
|
9995
9976
|
const key = process.platform === "win32" ? projectRoot.toLowerCase() : projectRoot;
|
|
@@ -10024,18 +10005,15 @@ async function installNpmPlugin(options) {
|
|
|
10024
10005
|
throw new Error(`Invalid plugin id: ${options.pluginId}`);
|
|
10025
10006
|
if (!VERSION.test(version))
|
|
10026
10007
|
throw new Error(`Invalid plugin version: ${version}`);
|
|
10027
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10028
|
-
return withProjectLock(
|
|
10008
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10009
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10029
10010
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10030
10011
|
if (!host)
|
|
10031
10012
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
10032
|
-
const hostId = Object.entries(mappingsOf(host)).find(([, value]) => value === name
|
|
10033
|
-
const targetRoot =
|
|
10034
|
-
? packageRoot
|
|
10035
|
-
: projectRoot;
|
|
10013
|
+
const hostId = Object.entries(mappingsOf(host)).find(([, value]) => value === name)?.[0];
|
|
10014
|
+
const targetRoot = dependencyRoot;
|
|
10036
10015
|
if (options.pluginId &&
|
|
10037
10016
|
mappingsOf(host)[options.pluginId] &&
|
|
10038
|
-
dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
|
|
10039
10017
|
mappingsOf(host)[options.pluginId] !== name)
|
|
10040
10018
|
throw new Error(`BUNDLED:${options.pluginId}`);
|
|
10041
10019
|
const original = readProjectManifest(targetRoot);
|
|
@@ -10064,24 +10042,33 @@ async function installNpmPlugin(options) {
|
|
|
10064
10042
|
"--save-exact",
|
|
10065
10043
|
"--no-fund",
|
|
10066
10044
|
"--no-audit",
|
|
10067
|
-
"--ignore-scripts"
|
|
10045
|
+
"--ignore-scripts",
|
|
10046
|
+
"--workspaces=false"
|
|
10068
10047
|
], targetRoot);
|
|
10069
10048
|
const entry = readPackageEntry(targetRoot, name);
|
|
10070
10049
|
const pluginId = options.pluginId || stringValue(objectValue(entry.metadata.elementspanel)?.id);
|
|
10071
10050
|
if (!PLUGIN_ID.test(pluginId))
|
|
10072
10051
|
throw new Error(`Invalid plugin id in ${name}.`);
|
|
10073
|
-
if (mappingsOf(host)[pluginId] &&
|
|
10074
|
-
dependenciesOf(host)[String(mappingsOf(host)[pluginId])] !== undefined &&
|
|
10075
|
-
mappingsOf(host)[pluginId] !== name)
|
|
10052
|
+
if (mappingsOf(host)[pluginId] && mappingsOf(host)[pluginId] !== name)
|
|
10076
10053
|
throw new Error(`Plugin id ${pluginId} belongs to a bundled dependency.`);
|
|
10077
10054
|
if (hostId && pluginId !== hostId)
|
|
10078
10055
|
throw new Error(`The package ${name} changed its plugin id from ${hostId} to ${pluginId}.`);
|
|
10079
10056
|
const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
|
|
10080
10057
|
if (mapped !== undefined && mapped !== name)
|
|
10081
10058
|
throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
|
|
10082
|
-
const record = recordFromPackage(pluginId, name,
|
|
10059
|
+
const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
|
|
10083
10060
|
if (!record)
|
|
10084
10061
|
throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
|
|
10062
|
+
if (side === "panel") {
|
|
10063
|
+
const expected = objectValue(objectValue(entry.metadata.elementspanel)?.panel)
|
|
10064
|
+
?.frontendAssets;
|
|
10065
|
+
const available = objectValue(host.elementspanel)?.frontendAssets;
|
|
10066
|
+
if ((hostId || expected !== undefined) &&
|
|
10067
|
+
(!Array.isArray(expected) ||
|
|
10068
|
+
!Array.isArray(available) ||
|
|
10069
|
+
expected.some((file) => typeof file !== "string" || !available.includes(file))))
|
|
10070
|
+
throw new Error(`Frontend assets in ${name} do not match this panel. Update the panel or install a matching plugin version.`);
|
|
10071
|
+
}
|
|
10085
10072
|
if (/^[0-9]/.test(version) && record.version !== version)
|
|
10086
10073
|
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
10087
10074
|
if (!process.env.EPANEL_PACKAGE_ROOT &&
|
|
@@ -10125,7 +10112,8 @@ async function installNpmPlugin(options) {
|
|
|
10125
10112
|
"--save",
|
|
10126
10113
|
"--no-fund",
|
|
10127
10114
|
"--no-audit",
|
|
10128
|
-
"--ignore-scripts"
|
|
10115
|
+
"--ignore-scripts",
|
|
10116
|
+
"--workspaces=false"
|
|
10129
10117
|
]
|
|
10130
10118
|
: [
|
|
10131
10119
|
"--prefix",
|
|
@@ -10134,7 +10122,8 @@ async function installNpmPlugin(options) {
|
|
|
10134
10122
|
name,
|
|
10135
10123
|
"--no-fund",
|
|
10136
10124
|
"--no-audit",
|
|
10137
|
-
"--ignore-scripts"
|
|
10125
|
+
"--ignore-scripts",
|
|
10126
|
+
"--workspaces=false"
|
|
10138
10127
|
], targetRoot);
|
|
10139
10128
|
}
|
|
10140
10129
|
catch (rollback) {
|
|
@@ -10158,22 +10147,29 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
|
10158
10147
|
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
10159
10148
|
if (isEssentialNpmPlugin(pluginId))
|
|
10160
10149
|
throw new Error(`The essential plugin "${pluginId}" cannot be uninstalled.`);
|
|
10161
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10162
|
-
return withProjectLock(
|
|
10163
|
-
const
|
|
10164
|
-
const bundledName = mappingsOf(host)[pluginId];
|
|
10165
|
-
const targetRoot = typeof bundledName === "string" &&
|
|
10166
|
-
dependenciesOf(host)[bundledName] !== undefined &&
|
|
10167
|
-
dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
|
|
10168
|
-
? packageRoot
|
|
10169
|
-
: projectRoot;
|
|
10150
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10151
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10152
|
+
const targetRoot = dependencyRoot;
|
|
10170
10153
|
const manifest = readProjectManifest(targetRoot);
|
|
10171
10154
|
const name = mappingsOf(manifest)[pluginId] ??
|
|
10172
|
-
listNpmPlugins(
|
|
10155
|
+
listNpmPlugins(options.side, { packageRoot, projectRoot, skipInvalid: true }).find((item) => item.pluginId === pluginId)?.name;
|
|
10173
10156
|
if (typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10174
10157
|
return null;
|
|
10175
|
-
const record = listNpmPlugins(
|
|
10176
|
-
|
|
10158
|
+
const record = listNpmPlugins(options.side, {
|
|
10159
|
+
packageRoot,
|
|
10160
|
+
projectRoot,
|
|
10161
|
+
skipInvalid: true
|
|
10162
|
+
}).find((item) => item.pluginId === pluginId);
|
|
10163
|
+
await runNpm([
|
|
10164
|
+
"--prefix",
|
|
10165
|
+
targetRoot,
|
|
10166
|
+
"uninstall",
|
|
10167
|
+
name,
|
|
10168
|
+
"--no-fund",
|
|
10169
|
+
"--no-audit",
|
|
10170
|
+
"--ignore-scripts",
|
|
10171
|
+
"--workspaces=false"
|
|
10172
|
+
], targetRoot);
|
|
10177
10173
|
const updated = readProjectManifest(targetRoot);
|
|
10178
10174
|
const plugins = { ...mappingsOf(updated) };
|
|
10179
10175
|
delete plugins[pluginId];
|
|
@@ -10347,11 +10343,11 @@ const plugin_npm_1 = __webpack_require__("../common/src/plugin_npm.ts");
|
|
|
10347
10343
|
/** Poll package boundaries, allowing npm to finish replacing files before reconciliation. */
|
|
10348
10344
|
function watchNpmPlugins(ctx, side, reload, changed) {
|
|
10349
10345
|
const stamp = () => {
|
|
10350
|
-
const { packageRoot,
|
|
10346
|
+
const { packageRoot, dependencyRoot } = (0, plugin_npm_1.npmPluginRoots)({ side });
|
|
10351
10347
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(packageRoot, "package.json")))
|
|
10352
10348
|
return "";
|
|
10353
10349
|
const files = [];
|
|
10354
|
-
for (const root of [packageRoot,
|
|
10350
|
+
for (const root of [packageRoot, dependencyRoot])
|
|
10355
10351
|
for (const name of [
|
|
10356
10352
|
"package.json",
|
|
10357
10353
|
"package-lock.json",
|
|
@@ -10375,7 +10371,7 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
10375
10371
|
let candidate = applied;
|
|
10376
10372
|
let busy = false;
|
|
10377
10373
|
ctx.setInterval(() => {
|
|
10378
|
-
if (busy || (0, plugin_npm_1.npmPluginOperationPending)())
|
|
10374
|
+
if (busy || (0, plugin_npm_1.npmPluginOperationPending)(side))
|
|
10379
10375
|
return;
|
|
10380
10376
|
try {
|
|
10381
10377
|
const next = stamp();
|
|
@@ -11460,6 +11456,226 @@ module.exports = require("stream/promises");
|
|
|
11460
11456
|
"use strict";
|
|
11461
11457
|
module.exports = require("util");
|
|
11462
11458
|
|
|
11459
|
+
/***/ },
|
|
11460
|
+
|
|
11461
|
+
/***/ "../../scripts/runtime/npm-plugins.cjs"
|
|
11462
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
11463
|
+
|
|
11464
|
+
const fs = __webpack_require__("node:fs");
|
|
11465
|
+
const path = __webpack_require__("node:path");
|
|
11466
|
+
const { createRequire } = __webpack_require__("node:module");
|
|
11467
|
+
|
|
11468
|
+
const readJson = (filename) => JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
11469
|
+
const readOptional = (filename) => {
|
|
11470
|
+
try {
|
|
11471
|
+
return readJson(filename);
|
|
11472
|
+
} catch (error) {
|
|
11473
|
+
if (error.code === "ENOENT") return null;
|
|
11474
|
+
throw error;
|
|
11475
|
+
}
|
|
11476
|
+
};
|
|
11477
|
+
const validId = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
11478
|
+
const validName = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
11479
|
+
|
|
11480
|
+
function packageManifest(root, name) {
|
|
11481
|
+
const localRequire = createRequire(path.join(root, "package.json"));
|
|
11482
|
+
const filename = (localRequire.resolve.paths(name) || [])
|
|
11483
|
+
.map((directory) => path.join(directory, name, "package.json"))
|
|
11484
|
+
.find((candidate) => fs.existsSync(candidate));
|
|
11485
|
+
if (!filename) throw new Error(`Missing npm package: ${name}`);
|
|
11486
|
+
return fs.realpathSync(filename);
|
|
11487
|
+
}
|
|
11488
|
+
|
|
11489
|
+
function within(root, filename) {
|
|
11490
|
+
const relative = path.relative(root, filename);
|
|
11491
|
+
return (
|
|
11492
|
+
relative === "" ||
|
|
11493
|
+
(relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))
|
|
11494
|
+
);
|
|
11495
|
+
}
|
|
11496
|
+
|
|
11497
|
+
function projectRoot(packageRoot) {
|
|
11498
|
+
if (process.env.EPANEL_PROJECT_ROOT) return path.resolve(process.env.EPANEL_PROJECT_ROOT);
|
|
11499
|
+
const parent = path.resolve(packageRoot, "..");
|
|
11500
|
+
if (path.basename(parent) === "core") return path.dirname(parent);
|
|
11501
|
+
// An installed runtime sits at <project>/node_modules/@scope/<side>; the
|
|
11502
|
+
// project itself is three levels above the package. A development checkout
|
|
11503
|
+
// sits below core/ and is handled above.
|
|
11504
|
+
const scope = parent;
|
|
11505
|
+
const nodeModules = path.dirname(scope);
|
|
11506
|
+
if (path.basename(nodeModules) === "node_modules" && path.basename(scope).startsWith("@")) {
|
|
11507
|
+
return path.dirname(nodeModules);
|
|
11508
|
+
}
|
|
11509
|
+
return parent;
|
|
11510
|
+
}
|
|
11511
|
+
|
|
11512
|
+
function projectManifestFile(packageRoot, side, options = {}) {
|
|
11513
|
+
const selectedSide =
|
|
11514
|
+
side ||
|
|
11515
|
+
readJson(path.join(packageRoot, "package.json")).elementspanel?.side ||
|
|
11516
|
+
path.basename(packageRoot);
|
|
11517
|
+
if (!["panel", "daemon"].includes(selectedSide)) throw new Error("Missing runtime side.");
|
|
11518
|
+
const directory =
|
|
11519
|
+
options.runtimeDirectory ||
|
|
11520
|
+
(!options.projectRoot && process.env.EPANEL_RUNTIME_ROOT) ||
|
|
11521
|
+
path.join(options.projectRoot || projectRoot(packageRoot), selectedSide);
|
|
11522
|
+
return path.join(path.resolve(directory), "package.json");
|
|
11523
|
+
}
|
|
11524
|
+
|
|
11525
|
+
function mappingOf(manifest) {
|
|
11526
|
+
const plugins = manifest?.elementspanel?.plugins;
|
|
11527
|
+
return plugins && typeof plugins === "object" && !Array.isArray(plugins) ? plugins : {};
|
|
11528
|
+
}
|
|
11529
|
+
|
|
11530
|
+
function dependenciesOf(manifest) {
|
|
11531
|
+
const dependencies = manifest?.dependencies;
|
|
11532
|
+
return dependencies && typeof dependencies === "object" ? dependencies : {};
|
|
11533
|
+
}
|
|
11534
|
+
|
|
11535
|
+
/**
|
|
11536
|
+
* Resolve plugins declared in the side's package.json, including hoisted npm
|
|
11537
|
+
* installations. The host catalogue reserves built-in ids without owning their
|
|
11538
|
+
* versions. Other explicitly mapped plugins remain dormant until enabled.
|
|
11539
|
+
* Runtime startup passes skipInvalid so an optional package being removed does
|
|
11540
|
+
* not stop the host; the caller separately validates the small set of core
|
|
11541
|
+
* plugins.
|
|
11542
|
+
*/
|
|
11543
|
+
function resolveNpmPlugins(packageRoot, side, options = {}) {
|
|
11544
|
+
const skipInvalid = options.skipInvalid === true;
|
|
11545
|
+
const host = readJson(path.join(packageRoot, "package.json"));
|
|
11546
|
+
const selectedSide = side || host.elementspanel?.side || path.basename(packageRoot);
|
|
11547
|
+
const projectFile = projectManifestFile(packageRoot, selectedSide, options);
|
|
11548
|
+
const project = readOptional(projectFile);
|
|
11549
|
+
const dependencyRoot = path.dirname(projectFile);
|
|
11550
|
+
|
|
11551
|
+
// The side manifest owns every dependency; the host only reserves identities.
|
|
11552
|
+
const configured = new Map();
|
|
11553
|
+
for (const [id, name] of Object.entries(mappingOf(project)))
|
|
11554
|
+
configured.set(id, { name, source: "project" });
|
|
11555
|
+
for (const name of Object.keys(dependenciesOf(project))) {
|
|
11556
|
+
if (!validName.test(name) || [...configured.values()].some((item) => item.name === name))
|
|
11557
|
+
continue;
|
|
11558
|
+
try {
|
|
11559
|
+
const metadata = readJson(packageManifest(dependencyRoot, name));
|
|
11560
|
+
const id = metadata.elementspanel?.id;
|
|
11561
|
+
if (validId.test(id) && !configured.has(id))
|
|
11562
|
+
configured.set(id, { name, source: "project", automatic: true });
|
|
11563
|
+
} catch {
|
|
11564
|
+
/* Ignore incomplete npm installations until the next scan. */
|
|
11565
|
+
}
|
|
11566
|
+
}
|
|
11567
|
+
for (const [id, name] of Object.entries(mappingOf(host))) {
|
|
11568
|
+
if (dependenciesOf(project)[name] !== undefined)
|
|
11569
|
+
configured.set(id, {
|
|
11570
|
+
name,
|
|
11571
|
+
source: "bundled",
|
|
11572
|
+
automatic: true
|
|
11573
|
+
});
|
|
11574
|
+
else if (configured.has(id)) {
|
|
11575
|
+
if (!skipInvalid) throw new Error(`Plugin id ${id} belongs to built-in package ${name}.`);
|
|
11576
|
+
configured.delete(id);
|
|
11577
|
+
}
|
|
11578
|
+
}
|
|
11579
|
+
|
|
11580
|
+
const projectDependencies = dependenciesOf(project);
|
|
11581
|
+
const folders = new Set();
|
|
11582
|
+
const records = [];
|
|
11583
|
+
|
|
11584
|
+
for (const [id, mapping] of configured) {
|
|
11585
|
+
const name = mapping.name;
|
|
11586
|
+
if (
|
|
11587
|
+
!validId.test(id) ||
|
|
11588
|
+
typeof name !== "string" ||
|
|
11589
|
+
!validName.test(name) ||
|
|
11590
|
+
projectDependencies[name] === undefined
|
|
11591
|
+
) {
|
|
11592
|
+
if (skipInvalid) continue;
|
|
11593
|
+
throw new Error(`Invalid npm plugin dependency: ${id}.`);
|
|
11594
|
+
}
|
|
11595
|
+
|
|
11596
|
+
let manifestPath;
|
|
11597
|
+
let failure;
|
|
11598
|
+
try {
|
|
11599
|
+
manifestPath = packageManifest(dependencyRoot, name);
|
|
11600
|
+
} catch (error) {
|
|
11601
|
+
failure = error;
|
|
11602
|
+
}
|
|
11603
|
+
if (!manifestPath) {
|
|
11604
|
+
if (skipInvalid) continue;
|
|
11605
|
+
throw new Error(`Missing npm plugin ${name}. Run npm install in ${dependencyRoot}.`, {
|
|
11606
|
+
cause: failure
|
|
11607
|
+
});
|
|
11608
|
+
}
|
|
11609
|
+
let metadata;
|
|
11610
|
+
try {
|
|
11611
|
+
metadata = readJson(manifestPath);
|
|
11612
|
+
} catch (error) {
|
|
11613
|
+
if (skipInvalid) continue;
|
|
11614
|
+
throw error;
|
|
11615
|
+
}
|
|
11616
|
+
const definition = metadata.elementspanel?.[selectedSide];
|
|
11617
|
+
// A project dependency may only ship one side; the other side simply does
|
|
11618
|
+
// not see it. A built-in plugin declared by the runtime must carry this side.
|
|
11619
|
+
if (!definition) {
|
|
11620
|
+
if (mapping.source === "project" || skipInvalid) continue;
|
|
11621
|
+
throw new Error(`Invalid ${selectedSide} entry in npm plugin ${name}.`);
|
|
11622
|
+
}
|
|
11623
|
+
const pluginRoot = path.dirname(manifestPath);
|
|
11624
|
+
if (
|
|
11625
|
+
typeof definition.directory !== "string" ||
|
|
11626
|
+
typeof definition.folder !== "string" ||
|
|
11627
|
+
!validId.test(definition.folder) ||
|
|
11628
|
+
path.isAbsolute(definition.directory)
|
|
11629
|
+
) {
|
|
11630
|
+
if (skipInvalid) continue;
|
|
11631
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
11632
|
+
}
|
|
11633
|
+
const directory = path.resolve(pluginRoot, definition.directory);
|
|
11634
|
+
if (directory === pluginRoot || !within(pluginRoot, directory)) {
|
|
11635
|
+
if (skipInvalid) continue;
|
|
11636
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
11637
|
+
}
|
|
11638
|
+
let entries;
|
|
11639
|
+
try {
|
|
11640
|
+
entries = readJson(path.join(directory, "plugin.json"));
|
|
11641
|
+
} catch (error) {
|
|
11642
|
+
if (skipInvalid) continue;
|
|
11643
|
+
throw error;
|
|
11644
|
+
}
|
|
11645
|
+
if (
|
|
11646
|
+
metadata.elementspanel?.id !== id ||
|
|
11647
|
+
typeof metadata.version !== "string" ||
|
|
11648
|
+
!metadata.version.trim() ||
|
|
11649
|
+
!entries ||
|
|
11650
|
+
typeof entries !== "object" ||
|
|
11651
|
+
Array.isArray(entries)
|
|
11652
|
+
) {
|
|
11653
|
+
if (skipInvalid) continue;
|
|
11654
|
+
throw new Error(`Invalid npm plugin identity or version in package.json: ${name}.`);
|
|
11655
|
+
}
|
|
11656
|
+
if (folders.has(definition.folder)) {
|
|
11657
|
+
if (skipInvalid) continue;
|
|
11658
|
+
throw new Error(`Duplicate npm plugin asset directory: ${definition.folder}.`);
|
|
11659
|
+
}
|
|
11660
|
+
folders.add(definition.folder);
|
|
11661
|
+
records.push({
|
|
11662
|
+
id,
|
|
11663
|
+
name,
|
|
11664
|
+
version: metadata.version,
|
|
11665
|
+
source: mapping.source,
|
|
11666
|
+
defaultEnabled: mapping.automatic === true || mapping.source !== "project",
|
|
11667
|
+
packageRoot: pluginRoot,
|
|
11668
|
+
directory,
|
|
11669
|
+
folder: definition.folder,
|
|
11670
|
+
dependencies: Object.keys(metadata.dependencies || {})
|
|
11671
|
+
});
|
|
11672
|
+
}
|
|
11673
|
+
return records;
|
|
11674
|
+
}
|
|
11675
|
+
|
|
11676
|
+
module.exports = { resolveNpmPlugins, projectManifestFile };
|
|
11677
|
+
|
|
11678
|
+
|
|
11463
11679
|
/***/ },
|
|
11464
11680
|
|
|
11465
11681
|
/***/ "../../scripts/workspace-layout.cjs"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementspanel/epanel-plugin-instance",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Application instance and Java runtime management.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Csituka_D <694428809@qq.com> (https://github.com/JessDaodao)",
|
|
@@ -39,7 +39,45 @@
|
|
|
39
39
|
"frontend/assets/style-0-style-10-_panel-plugin-build-entry_instance-242e9b23.css"
|
|
40
40
|
],
|
|
41
41
|
"directory": "panel",
|
|
42
|
-
"folder": "instance"
|
|
42
|
+
"folder": "instance",
|
|
43
|
+
"frontendAssets": [
|
|
44
|
+
"assets/AppDialog.vue_vue_type_style_index_0_lang-f1610327.js",
|
|
45
|
+
"assets/CardPanel-6fb07d57.js",
|
|
46
|
+
"assets/DesktopDialog-653072f1.js",
|
|
47
|
+
"assets/Loading.vue_vue_type_script_setup_true_lang-e02f05df.js",
|
|
48
|
+
"assets/PageToolbar-6c8b1cf6.js",
|
|
49
|
+
"assets/_elements-sdk_cordis-e3bebc89.js",
|
|
50
|
+
"assets/_elements-sdk_cosmokit-e4842f5c.js",
|
|
51
|
+
"assets/_plugin-vue_export-helper-c27b6911.js",
|
|
52
|
+
"assets/const-5d04f817.js",
|
|
53
|
+
"assets/const-9c0a1a51.js",
|
|
54
|
+
"assets/context-f49cfcce.js",
|
|
55
|
+
"assets/copy-9f2e18f6.js",
|
|
56
|
+
"assets/dayjs.min-25183c0a.js",
|
|
57
|
+
"assets/desktopNotice-d83e9e67.js",
|
|
58
|
+
"assets/htmlparser2-bcb8f9db.js",
|
|
59
|
+
"assets/i18n-66e8c48a.js",
|
|
60
|
+
"assets/index-c684efbd.js",
|
|
61
|
+
"assets/instance-5ec65e42.js",
|
|
62
|
+
"assets/instance_contract-0115efe5.js",
|
|
63
|
+
"assets/lodash-001e4f93.js",
|
|
64
|
+
"assets/msl-logo-699c8076.png",
|
|
65
|
+
"assets/node-e836f0a9.js",
|
|
66
|
+
"assets/nodes-5b8baedc.js",
|
|
67
|
+
"assets/protocol-97f7bab7.js",
|
|
68
|
+
"assets/router-ffe15376.js",
|
|
69
|
+
"assets/useAppRouters-32a87787.js",
|
|
70
|
+
"assets/useAppStateStore-e16e4edd.js",
|
|
71
|
+
"assets/useDefineApi-5b6599dc.js",
|
|
72
|
+
"assets/useInstanceActionAvailability-514826f4.js",
|
|
73
|
+
"assets/useKeyboardEvents-b70c8bcd.js",
|
|
74
|
+
"assets/useMountComponent-26d35a1e.js",
|
|
75
|
+
"assets/useOverviewInfo-f30aafac.js",
|
|
76
|
+
"assets/usePolling-73859228.js",
|
|
77
|
+
"assets/useScreen-7eb281ed.js",
|
|
78
|
+
"assets/vue-828bfe55.js",
|
|
79
|
+
"assets/vuetifyModal-47e2f27c.js"
|
|
80
|
+
]
|
|
43
81
|
},
|
|
44
82
|
"daemon": {
|
|
45
83
|
"priority": 40,
|
|
@@ -50,8 +88,8 @@
|
|
|
50
88
|
}
|
|
51
89
|
},
|
|
52
90
|
"peerDependencies": {
|
|
53
|
-
"@elementspanel/panel": "^1.0.
|
|
54
|
-
"@elementspanel/daemon": "^1.0.
|
|
91
|
+
"@elementspanel/panel": "^1.0.0",
|
|
92
|
+
"@elementspanel/daemon": "^1.0.0"
|
|
55
93
|
},
|
|
56
94
|
"peerDependenciesMeta": {
|
|
57
95
|
"@elementspanel/panel": {
|
package/panel/backend/index.cjs
CHANGED
|
@@ -10386,6 +10386,39 @@ async function loadPluginModule(entry, directory, revision) {
|
|
|
10386
10386
|
|
|
10387
10387
|
"use strict";
|
|
10388
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
|
+
})();
|
|
10389
10422
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10390
10423
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10391
10424
|
};
|
|
@@ -10405,6 +10438,8 @@ const path_1 = __importDefault(__webpack_require__("path"));
|
|
|
10405
10438
|
const module_1 = __webpack_require__("module");
|
|
10406
10439
|
const plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
10407
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"));
|
|
10408
10443
|
const PLUGIN_ID = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
10409
10444
|
const PACKAGE_NAME = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
10410
10445
|
const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/;
|
|
@@ -10446,11 +10481,20 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
|
10446
10481
|
return scope;
|
|
10447
10482
|
}
|
|
10448
10483
|
function npmPluginRoots(options = {}) {
|
|
10449
|
-
var _a, _b;
|
|
10484
|
+
var _a, _b, _c;
|
|
10450
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);
|
|
10451
10491
|
return {
|
|
10452
10492
|
packageRoot,
|
|
10453
|
-
projectRoot
|
|
10493
|
+
projectRoot,
|
|
10494
|
+
dependencyRoot: path_1.default.dirname(npmPlugins.projectManifestFile(packageRoot, side, {
|
|
10495
|
+
projectRoot,
|
|
10496
|
+
runtimeDirectory: process.env.EPANEL_RUNTIME_ROOT
|
|
10497
|
+
}))
|
|
10454
10498
|
};
|
|
10455
10499
|
}
|
|
10456
10500
|
function projectManifestFile(projectRoot) {
|
|
@@ -10481,15 +10525,10 @@ function pluginRecord(pluginId, name, source, packageRoot, directory, folder, ve
|
|
|
10481
10525
|
function readPackageEntry(packageRoot, name) {
|
|
10482
10526
|
// Read package boundaries directly: Node caches require.resolve() paths even
|
|
10483
10527
|
// after npm moves an installation between nested and hoisted node_modules.
|
|
10484
|
-
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
10489
|
-
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
10490
|
-
if (manifestPath)
|
|
10491
|
-
break;
|
|
10492
|
-
}
|
|
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));
|
|
10493
10532
|
if (!manifestPath)
|
|
10494
10533
|
throw new Error(`Missing npm plugin package: ${name}.`);
|
|
10495
10534
|
manifestPath = fs_extra_1.default.realpathSync(manifestPath);
|
|
@@ -10537,84 +10576,26 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
|
|
|
10537
10576
|
/**
|
|
10538
10577
|
* Every npm plugin the runtime can load for a side, built-in and project-installed.
|
|
10539
10578
|
*
|
|
10540
|
-
* Built-in package names
|
|
10541
|
-
*
|
|
10542
|
-
* A project package that does not describe the requested side is skipped instead of failing, which
|
|
10543
|
-
* 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.
|
|
10544
10581
|
*/
|
|
10545
10582
|
function listNpmPlugins(side, options = {}) {
|
|
10546
|
-
|
|
10547
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10548
|
-
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10549
|
-
if (!host)
|
|
10550
|
-
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
10551
|
-
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
10552
|
-
? null
|
|
10553
|
-
: readProjectManifest(projectRoot);
|
|
10554
|
-
const hostMappings = mappingsOf(host);
|
|
10555
|
-
const projectMappings = { ...mappingsOf(project) };
|
|
10556
|
-
for (const name of Object.keys(dependenciesOf(project))) {
|
|
10557
|
-
if (!PACKAGE_NAME.test(name) || Object.values(projectMappings).includes(name))
|
|
10558
|
-
continue;
|
|
10559
|
-
try {
|
|
10560
|
-
const entry = readPackageEntry(projectRoot, name);
|
|
10561
|
-
const id = stringValue((_a = objectValue(entry.metadata.elementspanel)) === null || _a === void 0 ? void 0 : _a.id);
|
|
10562
|
-
if (PLUGIN_ID.test(id) && projectMappings[id] === undefined)
|
|
10563
|
-
projectMappings[id] = name;
|
|
10564
|
-
}
|
|
10565
|
-
catch (_c) {
|
|
10566
|
-
/* npm may still be writing the package. */
|
|
10567
|
-
}
|
|
10568
|
-
}
|
|
10569
|
-
const mappings = new Map();
|
|
10570
|
-
for (const [pluginId, name] of Object.entries(projectMappings)) {
|
|
10571
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10572
|
-
continue;
|
|
10573
|
-
mappings.set(pluginId, { name, source: "project" });
|
|
10574
|
-
}
|
|
10575
|
-
for (const [pluginId, name] of Object.entries(hostMappings)) {
|
|
10576
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10577
|
-
continue;
|
|
10578
|
-
if (dependenciesOf(host)[name] === undefined)
|
|
10579
|
-
continue;
|
|
10580
|
-
mappings.set(pluginId, {
|
|
10581
|
-
name,
|
|
10582
|
-
source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
|
|
10583
|
-
});
|
|
10584
|
-
}
|
|
10585
|
-
const hostDependencies = dependenciesOf(host);
|
|
10586
|
-
const projectDependencies = dependenciesOf(project);
|
|
10587
|
-
const folders = new Set();
|
|
10583
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots({ ...options, side });
|
|
10588
10584
|
const records = [];
|
|
10589
|
-
for (const
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
entry = readPackageEntry(mapping.source === "project" ? projectRoot : packageRoot, mapping.name);
|
|
10599
|
-
}
|
|
10600
|
-
catch (error) {
|
|
10601
|
-
if (options.skipInvalid)
|
|
10602
|
-
continue;
|
|
10603
|
-
throw error;
|
|
10604
|
-
}
|
|
10605
|
-
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);
|
|
10606
10594
|
if (!record) {
|
|
10607
|
-
if (options.skipInvalid || mapping.source === "project")
|
|
10608
|
-
continue;
|
|
10609
|
-
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${mapping.name}.`);
|
|
10610
|
-
}
|
|
10611
|
-
const folder = record.folder;
|
|
10612
|
-
if (folders.has(folder)) {
|
|
10613
10595
|
if (options.skipInvalid)
|
|
10614
10596
|
continue;
|
|
10615
|
-
throw new Error(`
|
|
10597
|
+
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${item.name}.`);
|
|
10616
10598
|
}
|
|
10617
|
-
folders.add(folder);
|
|
10618
10599
|
records.push(record);
|
|
10619
10600
|
}
|
|
10620
10601
|
return records;
|
|
@@ -10713,10 +10694,9 @@ async function acquireProjectLock(projectRoot) {
|
|
|
10713
10694
|
}
|
|
10714
10695
|
}
|
|
10715
10696
|
}
|
|
10716
|
-
function npmPluginOperationPending() {
|
|
10717
|
-
const {
|
|
10718
|
-
return
|
|
10719
|
-
[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));
|
|
10720
10700
|
}
|
|
10721
10701
|
function withProjectLock(projectRoot, operation) {
|
|
10722
10702
|
var _a;
|
|
@@ -10752,19 +10732,16 @@ async function installNpmPlugin(options) {
|
|
|
10752
10732
|
throw new Error(`Invalid plugin id: ${options.pluginId}`);
|
|
10753
10733
|
if (!VERSION.test(version))
|
|
10754
10734
|
throw new Error(`Invalid plugin version: ${version}`);
|
|
10755
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10756
|
-
return withProjectLock(
|
|
10757
|
-
var _a, _b;
|
|
10735
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10736
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10737
|
+
var _a, _b, _c, _d, _e;
|
|
10758
10738
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
10759
10739
|
if (!host)
|
|
10760
10740
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
10761
|
-
const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name
|
|
10762
|
-
const targetRoot =
|
|
10763
|
-
? packageRoot
|
|
10764
|
-
: 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;
|
|
10765
10743
|
if (options.pluginId &&
|
|
10766
10744
|
mappingsOf(host)[options.pluginId] &&
|
|
10767
|
-
dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
|
|
10768
10745
|
mappingsOf(host)[options.pluginId] !== name)
|
|
10769
10746
|
throw new Error(`BUNDLED:${options.pluginId}`);
|
|
10770
10747
|
const original = readProjectManifest(targetRoot);
|
|
@@ -10774,7 +10751,7 @@ async function installNpmPlugin(options) {
|
|
|
10774
10751
|
try {
|
|
10775
10752
|
previousVersion = readPackageEntry(targetRoot, name).metadata.version || previous;
|
|
10776
10753
|
}
|
|
10777
|
-
catch (
|
|
10754
|
+
catch (_f) {
|
|
10778
10755
|
/* Keep the declared spec if the previous package is incomplete. */
|
|
10779
10756
|
}
|
|
10780
10757
|
}
|
|
@@ -10793,24 +10770,32 @@ async function installNpmPlugin(options) {
|
|
|
10793
10770
|
"--save-exact",
|
|
10794
10771
|
"--no-fund",
|
|
10795
10772
|
"--no-audit",
|
|
10796
|
-
"--ignore-scripts"
|
|
10773
|
+
"--ignore-scripts",
|
|
10774
|
+
"--workspaces=false"
|
|
10797
10775
|
], targetRoot);
|
|
10798
10776
|
const entry = readPackageEntry(targetRoot, name);
|
|
10799
10777
|
const pluginId = options.pluginId || stringValue((_b = objectValue(entry.metadata.elementspanel)) === null || _b === void 0 ? void 0 : _b.id);
|
|
10800
10778
|
if (!PLUGIN_ID.test(pluginId))
|
|
10801
10779
|
throw new Error(`Invalid plugin id in ${name}.`);
|
|
10802
|
-
if (mappingsOf(host)[pluginId] &&
|
|
10803
|
-
dependenciesOf(host)[String(mappingsOf(host)[pluginId])] !== undefined &&
|
|
10804
|
-
mappingsOf(host)[pluginId] !== name)
|
|
10780
|
+
if (mappingsOf(host)[pluginId] && mappingsOf(host)[pluginId] !== name)
|
|
10805
10781
|
throw new Error(`Plugin id ${pluginId} belongs to a bundled dependency.`);
|
|
10806
10782
|
if (hostId && pluginId !== hostId)
|
|
10807
10783
|
throw new Error(`The package ${name} changed its plugin id from ${hostId} to ${pluginId}.`);
|
|
10808
10784
|
const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
|
|
10809
10785
|
if (mapped !== undefined && mapped !== name)
|
|
10810
10786
|
throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
|
|
10811
|
-
const record = recordFromPackage(pluginId, name,
|
|
10787
|
+
const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
|
|
10812
10788
|
if (!record)
|
|
10813
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
|
+
}
|
|
10814
10799
|
if (/^[0-9]/.test(version) && record.version !== version)
|
|
10815
10800
|
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
10816
10801
|
if (!process.env.EPANEL_PACKAGE_ROOT &&
|
|
@@ -10854,7 +10839,8 @@ async function installNpmPlugin(options) {
|
|
|
10854
10839
|
"--save",
|
|
10855
10840
|
"--no-fund",
|
|
10856
10841
|
"--no-audit",
|
|
10857
|
-
"--ignore-scripts"
|
|
10842
|
+
"--ignore-scripts",
|
|
10843
|
+
"--workspaces=false"
|
|
10858
10844
|
]
|
|
10859
10845
|
: [
|
|
10860
10846
|
"--prefix",
|
|
@@ -10863,7 +10849,8 @@ async function installNpmPlugin(options) {
|
|
|
10863
10849
|
name,
|
|
10864
10850
|
"--no-fund",
|
|
10865
10851
|
"--no-audit",
|
|
10866
|
-
"--ignore-scripts"
|
|
10852
|
+
"--ignore-scripts",
|
|
10853
|
+
"--workspaces=false"
|
|
10867
10854
|
], targetRoot);
|
|
10868
10855
|
}
|
|
10869
10856
|
catch (rollback) {
|
|
@@ -10887,22 +10874,29 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
|
10887
10874
|
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
10888
10875
|
if (isEssentialNpmPlugin(pluginId))
|
|
10889
10876
|
throw new Error(`The essential plugin "${pluginId}" cannot be uninstalled.`);
|
|
10890
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
10891
|
-
return withProjectLock(
|
|
10877
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
10878
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
10892
10879
|
var _a, _b;
|
|
10893
|
-
const
|
|
10894
|
-
const bundledName = mappingsOf(host)[pluginId];
|
|
10895
|
-
const targetRoot = typeof bundledName === "string" &&
|
|
10896
|
-
dependenciesOf(host)[bundledName] !== undefined &&
|
|
10897
|
-
dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
|
|
10898
|
-
? packageRoot
|
|
10899
|
-
: projectRoot;
|
|
10880
|
+
const targetRoot = dependencyRoot;
|
|
10900
10881
|
const manifest = readProjectManifest(targetRoot);
|
|
10901
|
-
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;
|
|
10902
10883
|
if (typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
10903
10884
|
return null;
|
|
10904
|
-
const record = listNpmPlugins(
|
|
10905
|
-
|
|
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);
|
|
10906
10900
|
const updated = readProjectManifest(targetRoot);
|
|
10907
10901
|
const plugins = { ...mappingsOf(updated) };
|
|
10908
10902
|
delete plugins[pluginId];
|
|
@@ -11076,11 +11070,11 @@ const plugin_npm_1 = __webpack_require__("../common/src/plugin_npm.ts");
|
|
|
11076
11070
|
/** Poll package boundaries, allowing npm to finish replacing files before reconciliation. */
|
|
11077
11071
|
function watchNpmPlugins(ctx, side, reload, changed) {
|
|
11078
11072
|
const stamp = () => {
|
|
11079
|
-
const { packageRoot,
|
|
11073
|
+
const { packageRoot, dependencyRoot } = (0, plugin_npm_1.npmPluginRoots)({ side });
|
|
11080
11074
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(packageRoot, "package.json")))
|
|
11081
11075
|
return "";
|
|
11082
11076
|
const files = [];
|
|
11083
|
-
for (const root of [packageRoot,
|
|
11077
|
+
for (const root of [packageRoot, dependencyRoot])
|
|
11084
11078
|
for (const name of [
|
|
11085
11079
|
"package.json",
|
|
11086
11080
|
"package-lock.json",
|
|
@@ -11104,7 +11098,7 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
11104
11098
|
let candidate = applied;
|
|
11105
11099
|
let busy = false;
|
|
11106
11100
|
ctx.setInterval(() => {
|
|
11107
|
-
if (busy || (0, plugin_npm_1.npmPluginOperationPending)())
|
|
11101
|
+
if (busy || (0, plugin_npm_1.npmPluginOperationPending)(side))
|
|
11108
11102
|
return;
|
|
11109
11103
|
try {
|
|
11110
11104
|
const next = stamp();
|
|
@@ -12127,6 +12121,226 @@ module.exports = require("util");
|
|
|
12127
12121
|
"use strict";
|
|
12128
12122
|
module.exports = require("zlib");
|
|
12129
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
|
+
|
|
12130
12344
|
/***/ },
|
|
12131
12345
|
|
|
12132
12346
|
/***/ "../../scripts/workspace-layout.cjs"
|