@elementspanel/panel 1.0.1 → 1.0.2

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/app.js CHANGED
@@ -4204,9 +4204,9 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
4204
4204
  /**
4205
4205
  * Every npm plugin the runtime can load for a side, built-in and project-installed.
4206
4206
  *
4207
- * Built-in mappings win over a project mapping for the same id: a third-party
4208
- * package must not shadow a plugin that ships with the runtime. A project package
4209
- * that does not describe the requested side is skipped instead of failing, which
4207
+ * Built-in package names win over a project mapping for the same id. An explicit
4208
+ * project dependency on that same package selects the user's installed version.
4209
+ * A project package that does not describe the requested side is skipped instead of failing, which
4210
4210
  * is what lets a two-sided project share one dependency list between sides.
4211
4211
  */
4212
4212
  function listNpmPlugins(side, options = {}) {
@@ -4244,7 +4244,10 @@ function listNpmPlugins(side, options = {}) {
4244
4244
  continue;
4245
4245
  if (dependenciesOf(host)[name] === undefined)
4246
4246
  continue;
4247
- mappings.set(pluginId, { name, source: "bundled" });
4247
+ mappings.set(pluginId, {
4248
+ name,
4249
+ source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
4250
+ });
4248
4251
  }
4249
4252
  const hostDependencies = dependenciesOf(host);
4250
4253
  const projectDependencies = dependenciesOf(project);
@@ -4423,9 +4426,9 @@ async function installNpmPlugin(options) {
4423
4426
  if (!host)
4424
4427
  throw new Error(`Missing runtime package metadata: ${packageRoot}`);
4425
4428
  const hostId = (_a = Object.entries(mappingsOf(host)).find(([, value]) => value === name && dependenciesOf(host)[name] !== undefined)) === null || _a === void 0 ? void 0 : _a[0];
4426
- const targetRoot = hostId ? packageRoot : projectRoot;
4427
- if (hostId && isEssentialNpmPlugin(hostId))
4428
- throw new Error(`The essential plugin "${hostId}" cannot be replaced while running.`);
4429
+ const targetRoot = hostId && dependenciesOf(readProjectManifest(projectRoot))[name] === undefined
4430
+ ? packageRoot
4431
+ : projectRoot;
4429
4432
  if (options.pluginId &&
4430
4433
  mappingsOf(host)[options.pluginId] &&
4431
4434
  dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
@@ -4472,7 +4475,7 @@ async function installNpmPlugin(options) {
4472
4475
  const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
4473
4476
  if (mapped !== undefined && mapped !== name)
4474
4477
  throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
4475
- const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
4478
+ const record = recordFromPackage(pluginId, name, targetRoot === packageRoot ? "bundled" : "project", entry.root, entry.metadata, side);
4476
4479
  if (!record)
4477
4480
  throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
4478
4481
  if (/^[0-9]/.test(version) && record.version !== version)
@@ -4556,7 +4559,9 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
4556
4559
  var _a, _b;
4557
4560
  const host = readJson(path_1.default.join(packageRoot, "package.json"));
4558
4561
  const bundledName = mappingsOf(host)[pluginId];
4559
- const targetRoot = typeof bundledName === "string" && dependenciesOf(host)[bundledName] !== undefined
4562
+ const targetRoot = typeof bundledName === "string" &&
4563
+ dependenciesOf(host)[bundledName] !== undefined &&
4564
+ dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
4560
4565
  ? packageRoot
4561
4566
  : projectRoot;
4562
4567
  const manifest = readProjectManifest(targetRoot);
@@ -5584,7 +5589,7 @@ const ENTRY_CANDIDATES = [
5584
5589
  ];
5585
5590
  const FOUNDATION_PLUGIN_IDS = new Set(["i18n", "storage", "runtime"]);
5586
5591
  const ESSENTIAL_PLUGIN_IDS = new Set(["i18n", "storage", "runtime", "console"]);
5587
- const RESTART_PLUGIN_IDS = new Set([...ESSENTIAL_PLUGIN_IDS, "server", "config"]);
5592
+ const RESTART_CONFIG_PLUGIN_IDS = new Set([...ESSENTIAL_PLUGIN_IDS, "server", "config"]);
5588
5593
  const loaded = [];
5589
5594
  const frontendManifestWarnings = new Set();
5590
5595
  function warnFrontendManifest(message, error) {
@@ -5667,13 +5672,6 @@ async function installPlugin(plugin) {
5667
5672
  try {
5668
5673
  record.backendRevision = backendRevision(plugin);
5669
5674
  (0, mcsmanager_common_1.validatePluginCompatibility)(plugin.manifest.elements);
5670
- const previousRevision = codeRevisions.get(plugin.manifest.id);
5671
- if (RESTART_PLUGIN_IDS.has(plugin.manifest.id) &&
5672
- previousRevision &&
5673
- previousRevision !== record.backendRevision) {
5674
- record.restartRequired = true;
5675
- return record;
5676
- }
5677
5675
  codeRevisions.set(plugin.manifest.id, record.backendRevision);
5678
5676
  const module = toModule(await (0, mcsmanager_common_1.loadPluginModule)(plugin.entry, plugin.packageRoot || plugin.directory, record.backendRevision), plugin.manifest.id);
5679
5677
  if (!module)
@@ -5759,27 +5757,67 @@ async function reconcilePlugins() {
5759
5757
  onWarning: (message, error) => logger.warn(message, error)
5760
5758
  });
5761
5759
  const next = new Map(discovered.map((plugin) => [plugin.manifest.id, plugin]));
5762
- for (const running of [...loaded].reverse()) {
5760
+ const codeChanged = (running, plugin) => running.entry !== backendEntry(plugin) ||
5761
+ running.manifest.version !== plugin.manifest.version ||
5762
+ running.backendRevision !== backendRevision(plugin);
5763
+ // Foundation services own state used throughout the graph. Dispose consumers
5764
+ // before providers, then recreate every module before publishing new services.
5765
+ // This also prevents Cordis from restarting consumers during async cleanup.
5766
+ const reloadAll = loaded.some((running) => {
5763
5767
  const plugin = next.get(running.manifest.id);
5764
- const changed = plugin &&
5765
- (running.entry !== backendEntry(plugin) ||
5766
- running.manifest.version !== plugin.manifest.version ||
5767
- running.backendRevision !== backendRevision(plugin) ||
5768
- JSON.stringify(running.manifest.config) !== JSON.stringify(plugin.manifest.config));
5769
- if ((!plugin || changed) && !RESTART_PLUGIN_IDS.has(running.manifest.id)) {
5770
- await removeRunning(running.manifest.id);
5768
+ return plugin && (0, mcsmanager_common_1.isEssentialNpmPlugin)(running.manifest.id) && codeChanged(running, plugin);
5769
+ });
5770
+ if (reloadAll) {
5771
+ for (const running of loaded) {
5772
+ if ((0, mcsmanager_common_1.isEssentialNpmPlugin)(running.manifest.id) && !next.has(running.manifest.id))
5773
+ throw new Error(`Missing essential plugin during reload: ${running.manifest.id}`);
5774
+ }
5775
+ for (const plugin of discovered) {
5776
+ if (!(0, mcsmanager_common_1.isEssentialNpmPlugin)(plugin.manifest.id))
5777
+ continue;
5778
+ (0, mcsmanager_common_1.validatePluginCompatibility)(plugin.manifest.elements);
5779
+ if (!plugin.entry)
5780
+ throw new Error(`Missing essential plugin entry: ${plugin.manifest.id}`);
5781
+ }
5782
+ }
5783
+ // Publish listeners only after every route and authentication plugin is back.
5784
+ const started = reloadAll && context_1.ctx.lifecycle.isActive;
5785
+ if (reloadAll)
5786
+ context_1.ctx.lifecycle.isActive = false;
5787
+ try {
5788
+ if (reloadAll)
5789
+ await context_1.ctx.parallel("plugins/reloading");
5790
+ const removed = [];
5791
+ for (const running of [...loaded].reverse()) {
5792
+ const plugin = next.get(running.manifest.id);
5793
+ const changed = plugin &&
5794
+ (codeChanged(running, plugin) ||
5795
+ JSON.stringify(running.manifest.config) !== JSON.stringify(plugin.manifest.config));
5796
+ if (reloadAll ||
5797
+ ((!plugin || changed) && !RESTART_CONFIG_PLUGIN_IDS.has(running.manifest.id))) {
5798
+ await removeRunning(running.manifest.id);
5799
+ removed.push(running);
5800
+ }
5801
+ }
5802
+ for (const running of removed)
5771
5803
  forgetCachedModule(running.entry, running.packageRoot || running.directory);
5804
+ // Evict the whole batch before importing anything: dependencies may be shared
5805
+ // by several plugins, including the i18next instance used by the foundations.
5806
+ const pending = discovered.filter((plugin) => !loaded.some((record) => record.manifest.id === plugin.manifest.id));
5807
+ for (const plugin of pending)
5808
+ forgetCachedModule(plugin.entry, plugin.packageRoot || plugin.directory);
5809
+ for (const plugin of pending) {
5810
+ loaded.push(await installPlugin(plugin));
5811
+ await settle();
5772
5812
  }
5813
+ (0, mcsmanager_common_1.sortPlugins)(loaded);
5814
+ await settle();
5815
+ return loaded;
5773
5816
  }
5774
- for (const plugin of discovered) {
5775
- if (loaded.some((record) => record.manifest.id === plugin.manifest.id))
5776
- continue;
5777
- forgetCachedModule(plugin.entry, plugin.packageRoot || plugin.directory);
5778
- loaded.push(await installPlugin(plugin));
5817
+ finally {
5818
+ if (started)
5819
+ await context_1.ctx.start();
5779
5820
  }
5780
- (0, mcsmanager_common_1.sortPlugins)(loaded);
5781
- await settle();
5782
- return loaded;
5783
5821
  }
5784
5822
  /** Install or update an npm dependency, retaining the user's enablement on upgrades. */
5785
5823
  function installPanelNpmPlugin(options) {
@@ -6031,7 +6069,7 @@ function configurePanelPlugin(id, config) {
6031
6069
  (0, mcsmanager_common_1.validatePluginSettings)(plugin.manifest.configFields, config);
6032
6070
  (0, mcsmanager_common_1.writePluginOverride)(id, { config });
6033
6071
  // Core network/storage configuration is applied on restart; never tear down the reply path.
6034
- if (RESTART_PLUGIN_IDS.has(id)) {
6072
+ if (RESTART_CONFIG_PLUGIN_IDS.has(id)) {
6035
6073
  return {
6036
6074
  ...getPanelPluginInventory().find((item) => item.id === id),
6037
6075
  result: { saved: true, application: "restart-required" }