@elementspanel/epanel-plugin-config 1.0.4 → 1.0.6
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 +374 -113
- package/package.json +19 -5
- package/panel/backend/index.cjs +377 -117
- package/panel/frontend/assets/{style-0-_panel-plugin-build-entry_config-9641f087.css → style-0-_panel-plugin-build-entry_config-112f7940.css} +1 -1
- package/panel/frontend/panel-plugin-config-d3d27421.js +1 -0
- package/panel/plugin.json +1 -1
- package/panel/frontend/panel-plugin-config-440a77c3.js +0 -1
package/panel/backend/index.cjs
CHANGED
|
@@ -3286,6 +3286,7 @@ Object.defineProperty(exports, "arrayUnique", ({ enumerable: true, get: function
|
|
|
3286
3286
|
__exportStar(__webpack_require__("../common/src/plugin_contract.ts"), exports);
|
|
3287
3287
|
__exportStar(__webpack_require__("../common/src/plugin_overrides.ts"), exports);
|
|
3288
3288
|
__exportStar(__webpack_require__("../common/src/plugin_lifecycle.ts"), exports);
|
|
3289
|
+
__exportStar(__webpack_require__("../common/src/process_restart.ts"), exports);
|
|
3289
3290
|
__exportStar(__webpack_require__("../common/src/plugin_revision.ts"), exports);
|
|
3290
3291
|
__exportStar(__webpack_require__("../common/src/plugin_modules.ts"), exports);
|
|
3291
3292
|
__exportStar(__webpack_require__("../common/src/plugin_watch.ts"), exports);
|
|
@@ -4154,6 +4155,39 @@ async function loadPluginModule(entry, directory, revision) {
|
|
|
4154
4155
|
|
|
4155
4156
|
"use strict";
|
|
4156
4157
|
|
|
4158
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4159
|
+
if (k2 === undefined) k2 = k;
|
|
4160
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
4161
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
4162
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
4163
|
+
}
|
|
4164
|
+
Object.defineProperty(o, k2, desc);
|
|
4165
|
+
}) : (function(o, m, k, k2) {
|
|
4166
|
+
if (k2 === undefined) k2 = k;
|
|
4167
|
+
o[k2] = m[k];
|
|
4168
|
+
}));
|
|
4169
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
4170
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
4171
|
+
}) : function(o, v) {
|
|
4172
|
+
o["default"] = v;
|
|
4173
|
+
});
|
|
4174
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
4175
|
+
var ownKeys = function(o) {
|
|
4176
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
4177
|
+
var ar = [];
|
|
4178
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
4179
|
+
return ar;
|
|
4180
|
+
};
|
|
4181
|
+
return ownKeys(o);
|
|
4182
|
+
};
|
|
4183
|
+
return function (mod) {
|
|
4184
|
+
if (mod && mod.__esModule) return mod;
|
|
4185
|
+
var result = {};
|
|
4186
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
4187
|
+
__setModuleDefault(result, mod);
|
|
4188
|
+
return result;
|
|
4189
|
+
};
|
|
4190
|
+
})();
|
|
4157
4191
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4158
4192
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4159
4193
|
};
|
|
@@ -4173,6 +4207,8 @@ const path_1 = __importDefault(__webpack_require__("path"));
|
|
|
4173
4207
|
const module_1 = __webpack_require__("module");
|
|
4174
4208
|
const plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
4175
4209
|
const plugin_contract_1 = __webpack_require__("../common/src/plugin_contract.ts");
|
|
4210
|
+
// @ts-ignore Shared by the source runtime and the published npm launcher.
|
|
4211
|
+
const npmPlugins = __importStar(__webpack_require__("../../scripts/runtime/npm-plugins.cjs"));
|
|
4176
4212
|
const PLUGIN_ID = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
4177
4213
|
const PACKAGE_NAME = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
4178
4214
|
const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/;
|
|
@@ -4214,11 +4250,20 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
|
4214
4250
|
return scope;
|
|
4215
4251
|
}
|
|
4216
4252
|
function npmPluginRoots(options = {}) {
|
|
4217
|
-
var _a, _b;
|
|
4253
|
+
var _a, _b, _c;
|
|
4218
4254
|
const packageRoot = path_1.default.resolve((_a = options.packageRoot) !== null && _a !== void 0 ? _a : currentPackageRoot());
|
|
4255
|
+
const projectRoot = path_1.default.resolve((_b = options.projectRoot) !== null && _b !== void 0 ? _b : currentProjectRoot(packageRoot));
|
|
4256
|
+
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
4257
|
+
const side = options.side ||
|
|
4258
|
+
stringValue((_c = objectValue(host === null || host === void 0 ? void 0 : host.elementspanel)) === null || _c === void 0 ? void 0 : _c.side) ||
|
|
4259
|
+
path_1.default.basename(packageRoot);
|
|
4219
4260
|
return {
|
|
4220
4261
|
packageRoot,
|
|
4221
|
-
projectRoot
|
|
4262
|
+
projectRoot,
|
|
4263
|
+
dependencyRoot: path_1.default.dirname(npmPlugins.projectManifestFile(packageRoot, side, {
|
|
4264
|
+
projectRoot,
|
|
4265
|
+
runtimeDirectory: process.env.EPANEL_RUNTIME_ROOT
|
|
4266
|
+
}))
|
|
4222
4267
|
};
|
|
4223
4268
|
}
|
|
4224
4269
|
function projectManifestFile(projectRoot) {
|
|
@@ -4249,15 +4294,10 @@ function pluginRecord(pluginId, name, source, packageRoot, directory, folder, ve
|
|
|
4249
4294
|
function readPackageEntry(packageRoot, name) {
|
|
4250
4295
|
// Read package boundaries directly: Node caches require.resolve() paths even
|
|
4251
4296
|
// after npm moves an installation between nested and hoisted node_modules.
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
4257
|
-
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
4258
|
-
if (manifestPath)
|
|
4259
|
-
break;
|
|
4260
|
-
}
|
|
4297
|
+
const localRequire = (0, module_1.createRequire)(path_1.default.join(packageRoot, "package.json"));
|
|
4298
|
+
let manifestPath = (localRequire.resolve.paths(name) || [])
|
|
4299
|
+
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
4300
|
+
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
4261
4301
|
if (!manifestPath)
|
|
4262
4302
|
throw new Error(`Missing npm plugin package: ${name}.`);
|
|
4263
4303
|
manifestPath = fs_extra_1.default.realpathSync(manifestPath);
|
|
@@ -4305,84 +4345,26 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
|
|
|
4305
4345
|
/**
|
|
4306
4346
|
* Every npm plugin the runtime can load for a side, built-in and project-installed.
|
|
4307
4347
|
*
|
|
4308
|
-
* Built-in package names
|
|
4309
|
-
*
|
|
4310
|
-
* A project package that does not describe the requested side is skipped instead of failing, which
|
|
4311
|
-
* is what lets a two-sided project share one dependency list between sides.
|
|
4348
|
+
* Built-in package names reserve their plugin ids. The side manifest selects
|
|
4349
|
+
* the installed versions; a package without that side is skipped.
|
|
4312
4350
|
*/
|
|
4313
4351
|
function listNpmPlugins(side, options = {}) {
|
|
4314
|
-
|
|
4315
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
4316
|
-
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
4317
|
-
if (!host)
|
|
4318
|
-
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
4319
|
-
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
4320
|
-
? null
|
|
4321
|
-
: readProjectManifest(projectRoot);
|
|
4322
|
-
const hostMappings = mappingsOf(host);
|
|
4323
|
-
const projectMappings = { ...mappingsOf(project) };
|
|
4324
|
-
for (const name of Object.keys(dependenciesOf(project))) {
|
|
4325
|
-
if (!PACKAGE_NAME.test(name) || Object.values(projectMappings).includes(name))
|
|
4326
|
-
continue;
|
|
4327
|
-
try {
|
|
4328
|
-
const entry = readPackageEntry(projectRoot, name);
|
|
4329
|
-
const id = stringValue((_a = objectValue(entry.metadata.elementspanel)) === null || _a === void 0 ? void 0 : _a.id);
|
|
4330
|
-
if (PLUGIN_ID.test(id) && projectMappings[id] === undefined)
|
|
4331
|
-
projectMappings[id] = name;
|
|
4332
|
-
}
|
|
4333
|
-
catch (_c) {
|
|
4334
|
-
/* npm may still be writing the package. */
|
|
4335
|
-
}
|
|
4336
|
-
}
|
|
4337
|
-
const mappings = new Map();
|
|
4338
|
-
for (const [pluginId, name] of Object.entries(projectMappings)) {
|
|
4339
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
4340
|
-
continue;
|
|
4341
|
-
mappings.set(pluginId, { name, source: "project" });
|
|
4342
|
-
}
|
|
4343
|
-
for (const [pluginId, name] of Object.entries(hostMappings)) {
|
|
4344
|
-
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
4345
|
-
continue;
|
|
4346
|
-
if (dependenciesOf(host)[name] === undefined)
|
|
4347
|
-
continue;
|
|
4348
|
-
mappings.set(pluginId, {
|
|
4349
|
-
name,
|
|
4350
|
-
source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
|
|
4351
|
-
});
|
|
4352
|
-
}
|
|
4353
|
-
const hostDependencies = dependenciesOf(host);
|
|
4354
|
-
const projectDependencies = dependenciesOf(project);
|
|
4355
|
-
const folders = new Set();
|
|
4352
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots({ ...options, side });
|
|
4356
4353
|
const records = [];
|
|
4357
|
-
for (const
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
entry = readPackageEntry(mapping.source === "project" ? projectRoot : packageRoot, mapping.name);
|
|
4367
|
-
}
|
|
4368
|
-
catch (error) {
|
|
4369
|
-
if (options.skipInvalid)
|
|
4370
|
-
continue;
|
|
4371
|
-
throw error;
|
|
4372
|
-
}
|
|
4373
|
-
const record = recordFromPackage(pluginId, mapping.name, mapping.source, entry.root, entry.metadata, side);
|
|
4354
|
+
for (const item of npmPlugins.resolveNpmPlugins(packageRoot, side, {
|
|
4355
|
+
projectRoot,
|
|
4356
|
+
runtimeDirectory: dependencyRoot,
|
|
4357
|
+
skipInvalid: options.skipInvalid
|
|
4358
|
+
})) {
|
|
4359
|
+
const metadata = readJson(path_1.default.join(item.packageRoot, "package.json"));
|
|
4360
|
+
if (!metadata)
|
|
4361
|
+
continue;
|
|
4362
|
+
const record = recordFromPackage(item.id, item.name, item.source, item.packageRoot, metadata, side);
|
|
4374
4363
|
if (!record) {
|
|
4375
|
-
if (options.skipInvalid || mapping.source === "project")
|
|
4376
|
-
continue;
|
|
4377
|
-
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${mapping.name}.`);
|
|
4378
|
-
}
|
|
4379
|
-
const folder = record.folder;
|
|
4380
|
-
if (folders.has(folder)) {
|
|
4381
4364
|
if (options.skipInvalid)
|
|
4382
4365
|
continue;
|
|
4383
|
-
throw new Error(`
|
|
4366
|
+
throw new Error(`Invalid ${side !== null && side !== void 0 ? side : "plugin"} entry in npm plugin ${item.name}.`);
|
|
4384
4367
|
}
|
|
4385
|
-
folders.add(folder);
|
|
4386
4368
|
records.push(record);
|
|
4387
4369
|
}
|
|
4388
4370
|
return records;
|
|
@@ -4481,10 +4463,9 @@ async function acquireProjectLock(projectRoot) {
|
|
|
4481
4463
|
}
|
|
4482
4464
|
}
|
|
4483
4465
|
}
|
|
4484
|
-
function npmPluginOperationPending() {
|
|
4485
|
-
const {
|
|
4486
|
-
return
|
|
4487
|
-
[packageRoot, projectRoot].some((root) => fs_extra_1.default.existsSync(path_1.default.join(root, LOCK_NAME))));
|
|
4466
|
+
function npmPluginOperationPending(side) {
|
|
4467
|
+
const { dependencyRoot } = npmPluginRoots({ side });
|
|
4468
|
+
return operations.size > 0 || fs_extra_1.default.existsSync(path_1.default.join(dependencyRoot, LOCK_NAME));
|
|
4488
4469
|
}
|
|
4489
4470
|
function withProjectLock(projectRoot, operation) {
|
|
4490
4471
|
var _a;
|
|
@@ -4520,19 +4501,16 @@ async function installNpmPlugin(options) {
|
|
|
4520
4501
|
throw new Error(`Invalid plugin id: ${options.pluginId}`);
|
|
4521
4502
|
if (!VERSION.test(version))
|
|
4522
4503
|
throw new Error(`Invalid plugin version: ${version}`);
|
|
4523
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
4524
|
-
return withProjectLock(
|
|
4525
|
-
var _a, _b;
|
|
4504
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
4505
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
4506
|
+
var _a, _b, _c, _d, _e;
|
|
4526
4507
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
4527
4508
|
if (!host)
|
|
4528
4509
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
4529
|
-
const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name
|
|
4530
|
-
const targetRoot =
|
|
4531
|
-
? packageRoot
|
|
4532
|
-
: projectRoot;
|
|
4510
|
+
const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name)) === null || _a === void 0 ? void 0 : _a[0];
|
|
4511
|
+
const targetRoot = dependencyRoot;
|
|
4533
4512
|
if (options.pluginId &&
|
|
4534
4513
|
mappingsOf(host)[options.pluginId] &&
|
|
4535
|
-
dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
|
|
4536
4514
|
mappingsOf(host)[options.pluginId] !== name)
|
|
4537
4515
|
throw new Error(`BUNDLED:${options.pluginId}`);
|
|
4538
4516
|
const original = readProjectManifest(targetRoot);
|
|
@@ -4542,7 +4520,7 @@ async function installNpmPlugin(options) {
|
|
|
4542
4520
|
try {
|
|
4543
4521
|
previousVersion = readPackageEntry(targetRoot, name).metadata.version || previous;
|
|
4544
4522
|
}
|
|
4545
|
-
catch (
|
|
4523
|
+
catch (_f) {
|
|
4546
4524
|
/* Keep the declared spec if the previous package is incomplete. */
|
|
4547
4525
|
}
|
|
4548
4526
|
}
|
|
@@ -4561,24 +4539,32 @@ async function installNpmPlugin(options) {
|
|
|
4561
4539
|
"--save-exact",
|
|
4562
4540
|
"--no-fund",
|
|
4563
4541
|
"--no-audit",
|
|
4564
|
-
"--ignore-scripts"
|
|
4542
|
+
"--ignore-scripts",
|
|
4543
|
+
"--workspaces=false"
|
|
4565
4544
|
], targetRoot);
|
|
4566
4545
|
const entry = readPackageEntry(targetRoot, name);
|
|
4567
4546
|
const pluginId = options.pluginId || stringValue((_b = objectValue(entry.metadata.elementspanel)) === null || _b === void 0 ? void 0 : _b.id);
|
|
4568
4547
|
if (!PLUGIN_ID.test(pluginId))
|
|
4569
4548
|
throw new Error(`Invalid plugin id in ${name}.`);
|
|
4570
|
-
if (mappingsOf(host)[pluginId] &&
|
|
4571
|
-
dependenciesOf(host)[String(mappingsOf(host)[pluginId])] !== undefined &&
|
|
4572
|
-
mappingsOf(host)[pluginId] !== name)
|
|
4549
|
+
if (mappingsOf(host)[pluginId] && mappingsOf(host)[pluginId] !== name)
|
|
4573
4550
|
throw new Error(`Plugin id ${pluginId} belongs to a bundled dependency.`);
|
|
4574
4551
|
if (hostId && pluginId !== hostId)
|
|
4575
4552
|
throw new Error(`The package ${name} changed its plugin id from ${hostId} to ${pluginId}.`);
|
|
4576
4553
|
const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
|
|
4577
4554
|
if (mapped !== undefined && mapped !== name)
|
|
4578
4555
|
throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
|
|
4579
|
-
const record = recordFromPackage(pluginId, name,
|
|
4556
|
+
const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
|
|
4580
4557
|
if (!record)
|
|
4581
4558
|
throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
|
|
4559
|
+
if (side === "panel") {
|
|
4560
|
+
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;
|
|
4561
|
+
const available = (_e = objectValue(host.elementspanel)) === null || _e === void 0 ? void 0 : _e.frontendAssets;
|
|
4562
|
+
if ((hostId || expected !== undefined) &&
|
|
4563
|
+
(!Array.isArray(expected) ||
|
|
4564
|
+
!Array.isArray(available) ||
|
|
4565
|
+
expected.some((file) => typeof file !== "string" || !available.includes(file))))
|
|
4566
|
+
throw new Error(`Frontend assets in ${name} do not match this panel. Update the panel or install a matching plugin version.`);
|
|
4567
|
+
}
|
|
4582
4568
|
if (/^[0-9]/.test(version) && record.version !== version)
|
|
4583
4569
|
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
4584
4570
|
if (!process.env.EPANEL_PACKAGE_ROOT &&
|
|
@@ -4622,7 +4608,8 @@ async function installNpmPlugin(options) {
|
|
|
4622
4608
|
"--save",
|
|
4623
4609
|
"--no-fund",
|
|
4624
4610
|
"--no-audit",
|
|
4625
|
-
"--ignore-scripts"
|
|
4611
|
+
"--ignore-scripts",
|
|
4612
|
+
"--workspaces=false"
|
|
4626
4613
|
]
|
|
4627
4614
|
: [
|
|
4628
4615
|
"--prefix",
|
|
@@ -4631,7 +4618,8 @@ async function installNpmPlugin(options) {
|
|
|
4631
4618
|
name,
|
|
4632
4619
|
"--no-fund",
|
|
4633
4620
|
"--no-audit",
|
|
4634
|
-
"--ignore-scripts"
|
|
4621
|
+
"--ignore-scripts",
|
|
4622
|
+
"--workspaces=false"
|
|
4635
4623
|
], targetRoot);
|
|
4636
4624
|
}
|
|
4637
4625
|
catch (rollback) {
|
|
@@ -4655,22 +4643,29 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
|
4655
4643
|
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
4656
4644
|
if (isEssentialNpmPlugin(pluginId))
|
|
4657
4645
|
throw new Error(`The essential plugin "${pluginId}" cannot be uninstalled.`);
|
|
4658
|
-
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
4659
|
-
return withProjectLock(
|
|
4646
|
+
const { packageRoot, projectRoot, dependencyRoot } = npmPluginRoots(options);
|
|
4647
|
+
return withProjectLock(dependencyRoot, async () => {
|
|
4660
4648
|
var _a, _b;
|
|
4661
|
-
const
|
|
4662
|
-
const bundledName = mappingsOf(host)[pluginId];
|
|
4663
|
-
const targetRoot = typeof bundledName === "string" &&
|
|
4664
|
-
dependenciesOf(host)[bundledName] !== undefined &&
|
|
4665
|
-
dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
|
|
4666
|
-
? packageRoot
|
|
4667
|
-
: projectRoot;
|
|
4649
|
+
const targetRoot = dependencyRoot;
|
|
4668
4650
|
const manifest = readProjectManifest(targetRoot);
|
|
4669
|
-
const name = (_a = mappingsOf(manifest)[pluginId]) !== null && _a !== void 0 ? _a : (_b = listNpmPlugins(
|
|
4651
|
+
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;
|
|
4670
4652
|
if (typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
4671
4653
|
return null;
|
|
4672
|
-
const record = listNpmPlugins(
|
|
4673
|
-
|
|
4654
|
+
const record = listNpmPlugins(options.side, {
|
|
4655
|
+
packageRoot,
|
|
4656
|
+
projectRoot,
|
|
4657
|
+
skipInvalid: true
|
|
4658
|
+
}).find((item) => item.pluginId === pluginId);
|
|
4659
|
+
await runNpm([
|
|
4660
|
+
"--prefix",
|
|
4661
|
+
targetRoot,
|
|
4662
|
+
"uninstall",
|
|
4663
|
+
name,
|
|
4664
|
+
"--no-fund",
|
|
4665
|
+
"--no-audit",
|
|
4666
|
+
"--ignore-scripts",
|
|
4667
|
+
"--workspaces=false"
|
|
4668
|
+
], targetRoot);
|
|
4674
4669
|
const updated = readProjectManifest(targetRoot);
|
|
4675
4670
|
const plugins = { ...mappingsOf(updated) };
|
|
4676
4671
|
delete plugins[pluginId];
|
|
@@ -4844,11 +4839,11 @@ const plugin_npm_1 = __webpack_require__("../common/src/plugin_npm.ts");
|
|
|
4844
4839
|
/** Poll package boundaries, allowing npm to finish replacing files before reconciliation. */
|
|
4845
4840
|
function watchNpmPlugins(ctx, side, reload, changed) {
|
|
4846
4841
|
const stamp = () => {
|
|
4847
|
-
const { packageRoot,
|
|
4842
|
+
const { packageRoot, dependencyRoot } = (0, plugin_npm_1.npmPluginRoots)({ side });
|
|
4848
4843
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(packageRoot, "package.json")))
|
|
4849
4844
|
return "";
|
|
4850
4845
|
const files = [];
|
|
4851
|
-
for (const root of [packageRoot,
|
|
4846
|
+
for (const root of [packageRoot, dependencyRoot])
|
|
4852
4847
|
for (const name of [
|
|
4853
4848
|
"package.json",
|
|
4854
4849
|
"package-lock.json",
|
|
@@ -4872,7 +4867,7 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
4872
4867
|
let candidate = applied;
|
|
4873
4868
|
let busy = false;
|
|
4874
4869
|
ctx.setInterval(() => {
|
|
4875
|
-
if (busy || (0, plugin_npm_1.npmPluginOperationPending)())
|
|
4870
|
+
if (busy || (0, plugin_npm_1.npmPluginOperationPending)(side))
|
|
4876
4871
|
return;
|
|
4877
4872
|
try {
|
|
4878
4873
|
const next = stamp();
|
|
@@ -4903,6 +4898,51 @@ function watchNpmPlugins(ctx, side, reload, changed) {
|
|
|
4903
4898
|
}
|
|
4904
4899
|
|
|
4905
4900
|
|
|
4901
|
+
/***/ },
|
|
4902
|
+
|
|
4903
|
+
/***/ "../common/src/process_restart.ts"
|
|
4904
|
+
(__unused_webpack_module, exports) {
|
|
4905
|
+
|
|
4906
|
+
"use strict";
|
|
4907
|
+
|
|
4908
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4909
|
+
exports.isProcessRestartPending = isProcessRestartPending;
|
|
4910
|
+
exports.requestProcessRestart = requestProcessRestart;
|
|
4911
|
+
const RESTART = Symbol.for("elementspanel.process.restart");
|
|
4912
|
+
function isProcessRestartPending(ctx) {
|
|
4913
|
+
var _a;
|
|
4914
|
+
return ((_a = ctx.root[RESTART]) === null || _a === void 0 ? void 0 : _a.pending) === true;
|
|
4915
|
+
}
|
|
4916
|
+
/** The CLI retains instance processes and starts a fresh worker after this one exits. */
|
|
4917
|
+
function requestProcessRestart(ctx, settle, ready = async () => { }) {
|
|
4918
|
+
if (isProcessRestartPending(ctx))
|
|
4919
|
+
return true;
|
|
4920
|
+
if (process.env.EPANEL_SUPERVISED !== "1" || !process.connected || !process.send)
|
|
4921
|
+
return false;
|
|
4922
|
+
const state = { pending: true };
|
|
4923
|
+
ctx.root[RESTART] = state;
|
|
4924
|
+
const retainProcesses = () => new Promise((resolve, reject) => process.send({ type: "elementspanel:prepare-restart" }, (error) => error ? reject(error) : resolve()));
|
|
4925
|
+
setImmediate(() => {
|
|
4926
|
+
void (async () => {
|
|
4927
|
+
await ready();
|
|
4928
|
+
// Detach output consumers before cleanup so output and exits during the
|
|
4929
|
+
// restart are retained for the next daemon generation.
|
|
4930
|
+
await retainProcesses();
|
|
4931
|
+
await ctx.parallel("process/restarting");
|
|
4932
|
+
// A pending start can finish while restart hooks are awaiting it.
|
|
4933
|
+
await retainProcesses();
|
|
4934
|
+
await ctx.stop();
|
|
4935
|
+
await settle();
|
|
4936
|
+
process.send({ type: "elementspanel:restart" }, (error) => process.exit(error ? 1 : 0));
|
|
4937
|
+
})().catch((error) => {
|
|
4938
|
+
ctx.logger.error("Failed to restart the process:", error);
|
|
4939
|
+
process.exit(1);
|
|
4940
|
+
});
|
|
4941
|
+
});
|
|
4942
|
+
return true;
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
|
|
4906
4946
|
/***/ },
|
|
4907
4947
|
|
|
4908
4948
|
/***/ "../common/src/process_tools.ts"
|
|
@@ -5786,6 +5826,226 @@ module.exports = require("stream");
|
|
|
5786
5826
|
"use strict";
|
|
5787
5827
|
module.exports = require("string_decoder");
|
|
5788
5828
|
|
|
5829
|
+
/***/ },
|
|
5830
|
+
|
|
5831
|
+
/***/ "../../scripts/runtime/npm-plugins.cjs"
|
|
5832
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
5833
|
+
|
|
5834
|
+
const fs = __webpack_require__("node:fs");
|
|
5835
|
+
const path = __webpack_require__("node:path");
|
|
5836
|
+
const { createRequire } = __webpack_require__("node:module");
|
|
5837
|
+
|
|
5838
|
+
const readJson = (filename) => JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
5839
|
+
const readOptional = (filename) => {
|
|
5840
|
+
try {
|
|
5841
|
+
return readJson(filename);
|
|
5842
|
+
} catch (error) {
|
|
5843
|
+
if (error.code === "ENOENT") return null;
|
|
5844
|
+
throw error;
|
|
5845
|
+
}
|
|
5846
|
+
};
|
|
5847
|
+
const validId = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
5848
|
+
const validName = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
5849
|
+
|
|
5850
|
+
function packageManifest(root, name) {
|
|
5851
|
+
const localRequire = createRequire(path.join(root, "package.json"));
|
|
5852
|
+
const filename = (localRequire.resolve.paths(name) || [])
|
|
5853
|
+
.map((directory) => path.join(directory, name, "package.json"))
|
|
5854
|
+
.find((candidate) => fs.existsSync(candidate));
|
|
5855
|
+
if (!filename) throw new Error(`Missing npm package: ${name}`);
|
|
5856
|
+
return fs.realpathSync(filename);
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5859
|
+
function within(root, filename) {
|
|
5860
|
+
const relative = path.relative(root, filename);
|
|
5861
|
+
return (
|
|
5862
|
+
relative === "" ||
|
|
5863
|
+
(relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))
|
|
5864
|
+
);
|
|
5865
|
+
}
|
|
5866
|
+
|
|
5867
|
+
function projectRoot(packageRoot) {
|
|
5868
|
+
if (process.env.EPANEL_PROJECT_ROOT) return path.resolve(process.env.EPANEL_PROJECT_ROOT);
|
|
5869
|
+
const parent = path.resolve(packageRoot, "..");
|
|
5870
|
+
if (path.basename(parent) === "core") return path.dirname(parent);
|
|
5871
|
+
// An installed runtime sits at <project>/node_modules/@scope/<side>; the
|
|
5872
|
+
// project itself is three levels above the package. A development checkout
|
|
5873
|
+
// sits below core/ and is handled above.
|
|
5874
|
+
const scope = parent;
|
|
5875
|
+
const nodeModules = path.dirname(scope);
|
|
5876
|
+
if (path.basename(nodeModules) === "node_modules" && path.basename(scope).startsWith("@")) {
|
|
5877
|
+
return path.dirname(nodeModules);
|
|
5878
|
+
}
|
|
5879
|
+
return parent;
|
|
5880
|
+
}
|
|
5881
|
+
|
|
5882
|
+
function projectManifestFile(packageRoot, side, options = {}) {
|
|
5883
|
+
const selectedSide =
|
|
5884
|
+
side ||
|
|
5885
|
+
readJson(path.join(packageRoot, "package.json")).elementspanel?.side ||
|
|
5886
|
+
path.basename(packageRoot);
|
|
5887
|
+
if (!["panel", "daemon"].includes(selectedSide)) throw new Error("Missing runtime side.");
|
|
5888
|
+
const directory =
|
|
5889
|
+
options.runtimeDirectory ||
|
|
5890
|
+
(!options.projectRoot && process.env.EPANEL_RUNTIME_ROOT) ||
|
|
5891
|
+
path.join(options.projectRoot || projectRoot(packageRoot), selectedSide);
|
|
5892
|
+
return path.join(path.resolve(directory), "package.json");
|
|
5893
|
+
}
|
|
5894
|
+
|
|
5895
|
+
function mappingOf(manifest) {
|
|
5896
|
+
const plugins = manifest?.elementspanel?.plugins;
|
|
5897
|
+
return plugins && typeof plugins === "object" && !Array.isArray(plugins) ? plugins : {};
|
|
5898
|
+
}
|
|
5899
|
+
|
|
5900
|
+
function dependenciesOf(manifest) {
|
|
5901
|
+
const dependencies = manifest?.dependencies;
|
|
5902
|
+
return dependencies && typeof dependencies === "object" ? dependencies : {};
|
|
5903
|
+
}
|
|
5904
|
+
|
|
5905
|
+
/**
|
|
5906
|
+
* Resolve plugins declared in the side's package.json, including hoisted npm
|
|
5907
|
+
* installations. The host catalogue reserves built-in ids without owning their
|
|
5908
|
+
* versions. Other explicitly mapped plugins remain dormant until enabled.
|
|
5909
|
+
* Runtime startup passes skipInvalid so an optional package being removed does
|
|
5910
|
+
* not stop the host; the caller separately validates the small set of core
|
|
5911
|
+
* plugins.
|
|
5912
|
+
*/
|
|
5913
|
+
function resolveNpmPlugins(packageRoot, side, options = {}) {
|
|
5914
|
+
const skipInvalid = options.skipInvalid === true;
|
|
5915
|
+
const host = readJson(path.join(packageRoot, "package.json"));
|
|
5916
|
+
const selectedSide = side || host.elementspanel?.side || path.basename(packageRoot);
|
|
5917
|
+
const projectFile = projectManifestFile(packageRoot, selectedSide, options);
|
|
5918
|
+
const project = readOptional(projectFile);
|
|
5919
|
+
const dependencyRoot = path.dirname(projectFile);
|
|
5920
|
+
|
|
5921
|
+
// The side manifest owns every dependency; the host only reserves identities.
|
|
5922
|
+
const configured = new Map();
|
|
5923
|
+
for (const [id, name] of Object.entries(mappingOf(project)))
|
|
5924
|
+
configured.set(id, { name, source: "project" });
|
|
5925
|
+
for (const name of Object.keys(dependenciesOf(project))) {
|
|
5926
|
+
if (!validName.test(name) || [...configured.values()].some((item) => item.name === name))
|
|
5927
|
+
continue;
|
|
5928
|
+
try {
|
|
5929
|
+
const metadata = readJson(packageManifest(dependencyRoot, name));
|
|
5930
|
+
const id = metadata.elementspanel?.id;
|
|
5931
|
+
if (validId.test(id) && !configured.has(id))
|
|
5932
|
+
configured.set(id, { name, source: "project", automatic: true });
|
|
5933
|
+
} catch {
|
|
5934
|
+
/* Ignore incomplete npm installations until the next scan. */
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
for (const [id, name] of Object.entries(mappingOf(host))) {
|
|
5938
|
+
if (dependenciesOf(project)[name] !== undefined)
|
|
5939
|
+
configured.set(id, {
|
|
5940
|
+
name,
|
|
5941
|
+
source: "bundled",
|
|
5942
|
+
automatic: true
|
|
5943
|
+
});
|
|
5944
|
+
else if (configured.has(id)) {
|
|
5945
|
+
if (!skipInvalid) throw new Error(`Plugin id ${id} belongs to built-in package ${name}.`);
|
|
5946
|
+
configured.delete(id);
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
|
|
5950
|
+
const projectDependencies = dependenciesOf(project);
|
|
5951
|
+
const folders = new Set();
|
|
5952
|
+
const records = [];
|
|
5953
|
+
|
|
5954
|
+
for (const [id, mapping] of configured) {
|
|
5955
|
+
const name = mapping.name;
|
|
5956
|
+
if (
|
|
5957
|
+
!validId.test(id) ||
|
|
5958
|
+
typeof name !== "string" ||
|
|
5959
|
+
!validName.test(name) ||
|
|
5960
|
+
projectDependencies[name] === undefined
|
|
5961
|
+
) {
|
|
5962
|
+
if (skipInvalid) continue;
|
|
5963
|
+
throw new Error(`Invalid npm plugin dependency: ${id}.`);
|
|
5964
|
+
}
|
|
5965
|
+
|
|
5966
|
+
let manifestPath;
|
|
5967
|
+
let failure;
|
|
5968
|
+
try {
|
|
5969
|
+
manifestPath = packageManifest(dependencyRoot, name);
|
|
5970
|
+
} catch (error) {
|
|
5971
|
+
failure = error;
|
|
5972
|
+
}
|
|
5973
|
+
if (!manifestPath) {
|
|
5974
|
+
if (skipInvalid) continue;
|
|
5975
|
+
throw new Error(`Missing npm plugin ${name}. Run npm install in ${dependencyRoot}.`, {
|
|
5976
|
+
cause: failure
|
|
5977
|
+
});
|
|
5978
|
+
}
|
|
5979
|
+
let metadata;
|
|
5980
|
+
try {
|
|
5981
|
+
metadata = readJson(manifestPath);
|
|
5982
|
+
} catch (error) {
|
|
5983
|
+
if (skipInvalid) continue;
|
|
5984
|
+
throw error;
|
|
5985
|
+
}
|
|
5986
|
+
const definition = metadata.elementspanel?.[selectedSide];
|
|
5987
|
+
// A project dependency may only ship one side; the other side simply does
|
|
5988
|
+
// not see it. A built-in plugin declared by the runtime must carry this side.
|
|
5989
|
+
if (!definition) {
|
|
5990
|
+
if (mapping.source === "project" || skipInvalid) continue;
|
|
5991
|
+
throw new Error(`Invalid ${selectedSide} entry in npm plugin ${name}.`);
|
|
5992
|
+
}
|
|
5993
|
+
const pluginRoot = path.dirname(manifestPath);
|
|
5994
|
+
if (
|
|
5995
|
+
typeof definition.directory !== "string" ||
|
|
5996
|
+
typeof definition.folder !== "string" ||
|
|
5997
|
+
!validId.test(definition.folder) ||
|
|
5998
|
+
path.isAbsolute(definition.directory)
|
|
5999
|
+
) {
|
|
6000
|
+
if (skipInvalid) continue;
|
|
6001
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
6002
|
+
}
|
|
6003
|
+
const directory = path.resolve(pluginRoot, definition.directory);
|
|
6004
|
+
if (directory === pluginRoot || !within(pluginRoot, directory)) {
|
|
6005
|
+
if (skipInvalid) continue;
|
|
6006
|
+
throw new Error(`Npm plugin entry escapes its package: ${name}.`);
|
|
6007
|
+
}
|
|
6008
|
+
let entries;
|
|
6009
|
+
try {
|
|
6010
|
+
entries = readJson(path.join(directory, "plugin.json"));
|
|
6011
|
+
} catch (error) {
|
|
6012
|
+
if (skipInvalid) continue;
|
|
6013
|
+
throw error;
|
|
6014
|
+
}
|
|
6015
|
+
if (
|
|
6016
|
+
metadata.elementspanel?.id !== id ||
|
|
6017
|
+
typeof metadata.version !== "string" ||
|
|
6018
|
+
!metadata.version.trim() ||
|
|
6019
|
+
!entries ||
|
|
6020
|
+
typeof entries !== "object" ||
|
|
6021
|
+
Array.isArray(entries)
|
|
6022
|
+
) {
|
|
6023
|
+
if (skipInvalid) continue;
|
|
6024
|
+
throw new Error(`Invalid npm plugin identity or version in package.json: ${name}.`);
|
|
6025
|
+
}
|
|
6026
|
+
if (folders.has(definition.folder)) {
|
|
6027
|
+
if (skipInvalid) continue;
|
|
6028
|
+
throw new Error(`Duplicate npm plugin asset directory: ${definition.folder}.`);
|
|
6029
|
+
}
|
|
6030
|
+
folders.add(definition.folder);
|
|
6031
|
+
records.push({
|
|
6032
|
+
id,
|
|
6033
|
+
name,
|
|
6034
|
+
version: metadata.version,
|
|
6035
|
+
source: mapping.source,
|
|
6036
|
+
defaultEnabled: mapping.automatic === true || mapping.source !== "project",
|
|
6037
|
+
packageRoot: pluginRoot,
|
|
6038
|
+
directory,
|
|
6039
|
+
folder: definition.folder,
|
|
6040
|
+
dependencies: Object.keys(metadata.dependencies || {})
|
|
6041
|
+
});
|
|
6042
|
+
}
|
|
6043
|
+
return records;
|
|
6044
|
+
}
|
|
6045
|
+
|
|
6046
|
+
module.exports = { resolveNpmPlugins, projectManifestFile };
|
|
6047
|
+
|
|
6048
|
+
|
|
5789
6049
|
/***/ },
|
|
5790
6050
|
|
|
5791
6051
|
/***/ "../../scripts/workspace-layout.cjs"
|