@elementspanel/epanel-plugin-config 1.0.1 → 1.0.3

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.
@@ -1,10 +1,107 @@
1
1
  /******/ (() => { // webpackBootstrap
2
- /******/ "use strict";
3
2
  /******/ var __webpack_modules__ = ({
4
3
 
4
+ /***/ "../../plugins/config/daemon/src/backend/settings.ts"
5
+ (__unused_webpack_module, exports, __webpack_require__) {
6
+
7
+ "use strict";
8
+
9
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
10
+ exports.SettingsFormService = void 0;
11
+ const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
12
+ const cordis_1 = __webpack_require__("cordis");
13
+ const cosmokit_1 = __webpack_require__("cosmokit");
14
+ /** Configuration declarations are owned by the daemon config plugin. */
15
+ class SettingsFormService extends cordis_1.Service {
16
+ declarations = [];
17
+ constructor(ctx) {
18
+ super(ctx, "settingsForm", true);
19
+ }
20
+ declare(declaration) {
21
+ const entry = { id: this.ctx.name, declaration };
22
+ return this.ctx.effect(() => {
23
+ this.declarations.push(entry);
24
+ return () => (0, cosmokit_1.remove)(this.declarations, entry);
25
+ });
26
+ }
27
+ declared() {
28
+ return this.declarations.map((entry) => entry.id);
29
+ }
30
+ async read(id) {
31
+ const entry = this.declarations.find((item) => item.id === id);
32
+ if (!entry) {
33
+ const schema = this.ctx.plugins.configuration(id);
34
+ return schema.fields.length ? schema : null;
35
+ }
36
+ return { id, fields: entry.declaration.fields(), values: await entry.declaration.read() };
37
+ }
38
+ async write(id, values) {
39
+ const entry = this.declarations.find((item) => item.id === id);
40
+ if (!entry)
41
+ return (await this.ctx.plugins.configure(id, values)).result;
42
+ return this.ctx.plugins.runExclusive(async () => {
43
+ (0, mcsmanager_common_1.validatePluginSettings)(entry.declaration.fields(), values);
44
+ await entry.declaration.write(values);
45
+ return {
46
+ saved: true,
47
+ application: entry.declaration.restartRequired ? "restart-required" : "applied"
48
+ };
49
+ });
50
+ }
51
+ }
52
+ exports.SettingsFormService = SettingsFormService;
53
+
54
+
55
+ /***/ },
56
+
57
+ /***/ "../../plugins/config/daemon/src/i18n/index.ts"
58
+ (__unused_webpack_module, exports, __webpack_require__) {
59
+
60
+ "use strict";
61
+
62
+ var __importDefault = (this && this.__importDefault) || function (mod) {
63
+ return (mod && mod.__esModule) ? mod : { "default": mod };
64
+ };
65
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
66
+ exports.localeMessages = void 0;
67
+ const de_DE_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/de_DE.json"));
68
+ const en_US_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/en_US.json"));
69
+ const es_ES_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/es_ES.json"));
70
+ const fr_FR_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/fr_FR.json"));
71
+ const ja_JP_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/ja_JP.json"));
72
+ const ko_KR_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/ko_KR.json"));
73
+ const pt_BR_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/pt_BR.json"));
74
+ const ru_RU_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/ru_RU.json"));
75
+ const th_TH_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/th_TH.json"));
76
+ const tr_TR_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/tr_TR.json"));
77
+ const zh_CN_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/zh_CN.json"));
78
+ const zh_TW_json_1 = __importDefault(__webpack_require__("../../plugins/config/daemon/src/i18n/zh_TW.json"));
79
+ // The refusals this plugin's protocol handlers throw. The panel surfaces them
80
+ // verbatim on its plugin manager page, so they are translated here rather than
81
+ // in the panel: this daemon knows which of its own plugins may not be switched
82
+ // off remotely, and it answers in the language it was told to speak.
83
+ exports.localeMessages = {
84
+ de_de: de_DE_json_1.default,
85
+ en_us: en_US_json_1.default,
86
+ es_es: es_ES_json_1.default,
87
+ fr_fr: fr_FR_json_1.default,
88
+ ja_jp: ja_JP_json_1.default,
89
+ ko_kr: ko_KR_json_1.default,
90
+ pt_br: pt_BR_json_1.default,
91
+ ru_ru: ru_RU_json_1.default,
92
+ th_th: th_TH_json_1.default,
93
+ tr_tr: tr_TR_json_1.default,
94
+ zh_cn: zh_CN_json_1.default,
95
+ zh_tw: zh_TW_json_1.default
96
+ };
97
+
98
+
99
+ /***/ },
100
+
5
101
  /***/ "../common/src/array.ts"
6
102
  (__unused_webpack_module, exports) {
7
103
 
104
+ "use strict";
8
105
 
9
106
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10
107
  exports.arrayUnique = arrayUnique;
@@ -21,6 +118,7 @@ function arrayUnique(arr, felidName) {
21
118
  /***/ "../common/src/docker_utils.ts"
22
119
  (__unused_webpack_module, exports) {
23
120
 
121
+ "use strict";
24
122
 
25
123
  Object.defineProperty(exports, "__esModule", ({ value: true }));
26
124
  exports.normalizeDockerArchitecture = normalizeDockerArchitecture;
@@ -63,6 +161,7 @@ function normalizeDockerPlatform(platform) {
63
161
  /***/ "../common/src/global_variable.ts"
64
162
  (__unused_webpack_module, exports) {
65
163
 
164
+ "use strict";
66
165
 
67
166
  Object.defineProperty(exports, "__esModule", ({ value: true }));
68
167
  class GlobalVariable {
@@ -90,6 +189,7 @@ exports["default"] = GlobalVariable;
90
189
  /***/ "../common/src/index.ts"
91
190
  (__unused_webpack_module, exports, __webpack_require__) {
92
191
 
192
+ "use strict";
93
193
 
94
194
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
95
195
  if (k2 === undefined) k2 = k;
@@ -173,6 +273,7 @@ Object.defineProperty(exports, "normalizeDockerPlatform", ({ enumerable: true, g
173
273
  /***/ "../common/src/instance_stream.ts"
174
274
  (__unused_webpack_module, exports) {
175
275
 
276
+ "use strict";
176
277
 
177
278
  Object.defineProperty(exports, "__esModule", ({ value: true }));
178
279
  // Application instance data stream forwarding adapter
@@ -232,6 +333,7 @@ exports["default"] = InstanceStreamListener;
232
333
  /***/ "../common/src/mcping.ts"
233
334
  (__unused_webpack_module, exports, __webpack_require__) {
234
335
 
336
+ "use strict";
235
337
 
236
338
  var __importDefault = (this && this.__importDefault) || function (mod) {
237
339
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -350,6 +452,7 @@ exports["default"] = PingMinecraftServer;
350
452
  /***/ "../common/src/plugin_contract.ts"
351
453
  (__unused_webpack_module, exports) {
352
454
 
455
+ "use strict";
353
456
 
354
457
  Object.defineProperty(exports, "__esModule", ({ value: true }));
355
458
  exports.PLUGIN_SDK_VERSION = exports.PLUGIN_API_VERSION = void 0;
@@ -516,6 +619,7 @@ function validatePluginSettings(fields, values) {
516
619
  /***/ "../common/src/plugin_lifecycle.ts"
517
620
  (__unused_webpack_module, exports) {
518
621
 
622
+ "use strict";
519
623
 
520
624
  Object.defineProperty(exports, "__esModule", ({ value: true }));
521
625
  exports.trackPluginDisposal = trackPluginDisposal;
@@ -582,6 +686,7 @@ function trackPluginDisposal(ctx) {
582
686
  /***/ "../common/src/plugin_manifest.ts"
583
687
  (__unused_webpack_module, exports, __webpack_require__) {
584
688
 
689
+ "use strict";
585
690
 
586
691
  var __importDefault = (this && this.__importDefault) || function (mod) {
587
692
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -637,7 +742,7 @@ function objectValue(value) {
637
742
  * keep it at the package root, with runtime metadata under elementspanel.<side>.
638
743
  * Stop at the first package boundary so a host's metadata cannot reach a plugin.
639
744
  */
640
- function readPackageMetadata(directory, id) {
745
+ function readPackageMetadata(directory) {
641
746
  const pluginDirectory = node_path_1.default.resolve(directory);
642
747
  let current = pluginDirectory;
643
748
  while (true) {
@@ -649,12 +754,19 @@ function readPackageMetadata(directory, id) {
649
754
  .map(objectValue)
650
755
  .find((side) => typeof side.directory === "string" &&
651
756
  node_path_1.default.resolve(current, side.directory) === pluginDirectory);
652
- if (current !== pluginDirectory && (packageId !== id || !definition))
757
+ if (current !== pluginDirectory && (typeof packageId !== "string" || !definition))
653
758
  return {};
654
759
  const { directory: _directory, folder: _folder, ...sideMetadata } = definition ?? {};
655
- const result = { ...metadata, ...shared, ...sideMetadata };
760
+ const result = {
761
+ ...metadata,
762
+ ...shared,
763
+ ...sideMetadata,
764
+ ...(packageId === undefined ? {} : { id: packageId })
765
+ };
766
+ if (metadata.version !== undefined)
767
+ result.version = metadata.version;
656
768
  // npm's main/entry fields do not define a side's execution entry.
657
- for (const field of ["dual", ...ENTRY_FIELDS])
769
+ for (const field of ENTRY_FIELDS)
658
770
  delete result[field];
659
771
  return result;
660
772
  }
@@ -664,7 +776,7 @@ function readPackageMetadata(directory, id) {
664
776
  current = parent;
665
777
  }
666
778
  }
667
- /** Merges package metadata with a plugin's identity and entries. Legacy manifests still load. */
779
+ /** Combines execution entries with package metadata. Legacy manifests still load. */
668
780
  function readPluginManifest(directory, onWarning, fallbackId = node_path_1.default.basename(directory)) {
669
781
  for (const file of MANIFEST_FILES) {
670
782
  const filePath = node_path_1.default.join(directory, file);
@@ -674,17 +786,22 @@ function readPluginManifest(directory, onWarning, fallbackId = node_path_1.defau
674
786
  const value = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
675
787
  if (!value || typeof value !== "object" || Array.isArray(value))
676
788
  return null;
677
- const id = typeof value.id === "string" ? value.id : fallbackId;
789
+ const packageMetadata = readPackageMetadata(directory);
790
+ const id = typeof packageMetadata.id === "string"
791
+ ? packageMetadata.id
792
+ : typeof value.id === "string"
793
+ ? value.id
794
+ : fallbackId;
678
795
  if (!id.trim())
679
796
  return null;
680
797
  const manifest = {
681
798
  ...value,
682
- ...readPackageMetadata(directory, id.trim()),
799
+ ...packageMetadata,
683
800
  id: id.trim()
684
801
  };
685
- // Identity and execution paths always belong to plugin.json. Package
686
- // metadata wins for descriptions, priority, configuration and dependencies.
687
- for (const field of ["version", "dual", ...ENTRY_FIELDS]) {
802
+ // Only execution paths come from plugin.json; package.json owns identity,
803
+ // version, dual status and all other metadata.
804
+ for (const field of ENTRY_FIELDS) {
688
805
  if (value[field] !== undefined)
689
806
  manifest[field] = value[field];
690
807
  }
@@ -811,6 +928,7 @@ function sortPlugins(plugins) {
811
928
  /***/ "../common/src/plugin_modules.ts"
812
929
  (__unused_webpack_module, exports, __webpack_require__) {
813
930
 
931
+ "use strict";
814
932
 
815
933
  var __importDefault = (this && this.__importDefault) || function (mod) {
816
934
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -982,6 +1100,7 @@ async function loadPluginModule(entry, directory, revision) {
982
1100
  /***/ "../common/src/plugin_npm.ts"
983
1101
  (__unused_webpack_module, exports, __webpack_require__) {
984
1102
 
1103
+ "use strict";
985
1104
 
986
1105
  var __importDefault = (this && this.__importDefault) || function (mod) {
987
1106
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -1026,7 +1145,7 @@ function stringValue(value) {
1026
1145
  return typeof value === "string" ? value : "";
1027
1146
  }
1028
1147
  function currentPackageRoot() {
1029
- return path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.cwd());
1148
+ return path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.env.EPANEL_SOURCE_ROOT || process.cwd());
1030
1149
  }
1031
1150
  function currentProjectRoot(packageRoot = currentPackageRoot()) {
1032
1151
  // The npm worker sets EPANEL_PROJECT_ROOT to the installation directory. In a
@@ -1034,6 +1153,8 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
1034
1153
  if (process.env.EPANEL_PROJECT_ROOT)
1035
1154
  return path_1.default.resolve(process.env.EPANEL_PROJECT_ROOT);
1036
1155
  const scope = path_1.default.resolve(packageRoot, "..");
1156
+ if (path_1.default.basename(scope) === "core")
1157
+ return path_1.default.dirname(scope);
1037
1158
  const nodeModules = path_1.default.dirname(scope);
1038
1159
  if (path_1.default.basename(nodeModules) === "node_modules" && path_1.default.basename(scope).startsWith("@"))
1039
1160
  return path_1.default.dirname(nodeModules);
@@ -1126,9 +1247,9 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
1126
1247
  /**
1127
1248
  * Every npm plugin the runtime can load for a side, built-in and project-installed.
1128
1249
  *
1129
- * Built-in mappings win over a project mapping for the same id: a third-party
1130
- * package must not shadow a plugin that ships with the runtime. A project package
1131
- * that does not describe the requested side is skipped instead of failing, which
1250
+ * Built-in package names win over a project mapping for the same id. An explicit
1251
+ * project dependency on that same package selects the user's installed version.
1252
+ * A project package that does not describe the requested side is skipped instead of failing, which
1132
1253
  * is what lets a two-sided project share one dependency list between sides.
1133
1254
  */
1134
1255
  function listNpmPlugins(side, options = {}) {
@@ -1165,7 +1286,10 @@ function listNpmPlugins(side, options = {}) {
1165
1286
  continue;
1166
1287
  if (dependenciesOf(host)[name] === undefined)
1167
1288
  continue;
1168
- mappings.set(pluginId, { name, source: "bundled" });
1289
+ mappings.set(pluginId, {
1290
+ name,
1291
+ source: dependenciesOf(project)[name] === undefined ? "bundled" : "project"
1292
+ });
1169
1293
  }
1170
1294
  const hostDependencies = dependenciesOf(host);
1171
1295
  const projectDependencies = dependenciesOf(project);
@@ -1340,9 +1464,9 @@ async function installNpmPlugin(options) {
1340
1464
  if (!host)
1341
1465
  throw new Error(`Missing runtime package metadata: ${packageRoot}`);
1342
1466
  const hostId = Object.entries(mappingsOf(host)).find(([, value]) => value === name && dependenciesOf(host)[name] !== undefined)?.[0];
1343
- const targetRoot = hostId ? packageRoot : projectRoot;
1344
- if (hostId && isEssentialNpmPlugin(hostId))
1345
- throw new Error(`The essential plugin "${hostId}" cannot be replaced while running.`);
1467
+ const targetRoot = hostId && dependenciesOf(readProjectManifest(projectRoot))[name] === undefined
1468
+ ? packageRoot
1469
+ : projectRoot;
1346
1470
  if (options.pluginId &&
1347
1471
  mappingsOf(host)[options.pluginId] &&
1348
1472
  dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
@@ -1389,7 +1513,7 @@ async function installNpmPlugin(options) {
1389
1513
  const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
1390
1514
  if (mapped !== undefined && mapped !== name)
1391
1515
  throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
1392
- const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
1516
+ const record = recordFromPackage(pluginId, name, targetRoot === packageRoot ? "bundled" : "project", entry.root, entry.metadata, side);
1393
1517
  if (!record)
1394
1518
  throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
1395
1519
  if (/^[0-9]/.test(version) && record.version !== version)
@@ -1472,7 +1596,9 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
1472
1596
  return withProjectLock(projectRoot, async () => {
1473
1597
  const host = readJson(path_1.default.join(packageRoot, "package.json"));
1474
1598
  const bundledName = mappingsOf(host)[pluginId];
1475
- const targetRoot = typeof bundledName === "string" && dependenciesOf(host)[bundledName] !== undefined
1599
+ const targetRoot = typeof bundledName === "string" &&
1600
+ dependenciesOf(host)[bundledName] !== undefined &&
1601
+ dependenciesOf(readProjectManifest(projectRoot))[bundledName] === undefined
1476
1602
  ? packageRoot
1477
1603
  : projectRoot;
1478
1604
  const manifest = readProjectManifest(targetRoot);
@@ -1497,6 +1623,7 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
1497
1623
  /***/ "../common/src/plugin_overrides.ts"
1498
1624
  (__unused_webpack_module, exports, __webpack_require__) {
1499
1625
 
1626
+ "use strict";
1500
1627
 
1501
1628
  var __importDefault = (this && this.__importDefault) || function (mod) {
1502
1629
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -1585,6 +1712,7 @@ function writePluginOverride(id, patch, filename = pluginOverridesPath()) {
1585
1712
  /***/ "../common/src/plugin_revision.ts"
1586
1713
  (__unused_webpack_module, exports, __webpack_require__) {
1587
1714
 
1715
+ "use strict";
1588
1716
 
1589
1717
  var __importDefault = (this && this.__importDefault) || function (mod) {
1590
1718
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -1640,6 +1768,7 @@ function pluginDirectoryRevision(directory) {
1640
1768
  /***/ "../common/src/plugin_watch.ts"
1641
1769
  (__unused_webpack_module, exports, __webpack_require__) {
1642
1770
 
1771
+ "use strict";
1643
1772
 
1644
1773
  var __importDefault = (this && this.__importDefault) || function (mod) {
1645
1774
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -1716,6 +1845,7 @@ function watchNpmPlugins(ctx, side, reload, changed) {
1716
1845
  /***/ "../common/src/process_tools.ts"
1717
1846
  (__unused_webpack_module, exports, __webpack_require__) {
1718
1847
 
1848
+ "use strict";
1719
1849
 
1720
1850
  var __importDefault = (this && this.__importDefault) || function (mod) {
1721
1851
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -1880,6 +2010,7 @@ function killProcess(pid, process, signal) {
1880
2010
  /***/ "../common/src/query_wrapper.ts"
1881
2011
  (__unused_webpack_module, exports) {
1882
2012
 
2013
+ "use strict";
1883
2014
 
1884
2015
  Object.defineProperty(exports, "__esModule", ({ value: true }));
1885
2016
  exports.QueryWrapper = exports.LocalFileSource = exports.MySqlSource = exports.QueryMapWrapper = void 0;
@@ -1993,6 +2124,7 @@ exports.QueryWrapper = QueryWrapper;
1993
2124
  /***/ "../common/src/runtime_paths.ts"
1994
2125
  (__unused_webpack_module, exports, __webpack_require__) {
1995
2126
 
2127
+ "use strict";
1996
2128
 
1997
2129
  var __importDefault = (this && this.__importDefault) || function (mod) {
1998
2130
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -2007,22 +2139,24 @@ exports.ensureExecutable = ensureExecutable;
2007
2139
  const node_fs_1 = __importDefault(__webpack_require__("node:fs"));
2008
2140
  const node_os_1 = __importDefault(__webpack_require__("node:os"));
2009
2141
  const node_path_1 = __importDefault(__webpack_require__("node:path"));
2142
+ // @ts-ignore Shared source layout is also consumed by the Node build tools.
2143
+ const workspace_layout_cjs_1 = __webpack_require__("../../scripts/workspace-layout.cjs");
2010
2144
  /** Set by the npm worker before any application module is loaded. */
2011
2145
  function isPackagedRuntime() {
2012
2146
  return Boolean(process.env.EPANEL_PACKAGE_ROOT);
2013
2147
  }
2014
2148
  /** Code and bundled assets belong to the package; cwd always belongs to the user. */
2015
2149
  function packagePath(...parts) {
2016
- return node_path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.cwd(), ...parts);
2150
+ return node_path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.env.EPANEL_SOURCE_ROOT || process.cwd(), ...parts);
2017
2151
  }
2018
2152
  function npmPluginRoots(side) {
2019
2153
  // The same resolver is used by the CLI before the bundled application starts.
2020
- // A development checkout keeps it in the repository, beside the side packages,
2154
+ // A development checkout keeps it in the repository above core/<side>,
2021
2155
  // so project-installed npm plugins work there as well.
2022
2156
  const runtimeRequire = eval("require");
2023
2157
  const resolver = isPackagedRuntime()
2024
2158
  ? packagePath("runtime/npm-plugins.cjs")
2025
- : node_path_1.default.resolve(packagePath(), "..", "scripts", "runtime", "npm-plugins.cjs");
2159
+ : node_path_1.default.resolve(packagePath(), "../..", "scripts", "runtime", "npm-plugins.cjs");
2026
2160
  // A development process may run from a fixture directory without a runtime
2027
2161
  // package; there is nothing to resolve in that case.
2028
2162
  if (!node_fs_1.default.existsSync(node_path_1.default.join(packagePath(), "package.json")))
@@ -2043,9 +2177,16 @@ function npmPluginRoots(side) {
2043
2177
  }));
2044
2178
  }
2045
2179
  function packagePluginRoots(side) {
2180
+ const sourceCheckout = process.env.EPANEL_SOURCE_ROOT || node_path_1.default.basename(node_path_1.default.dirname(packagePath())) === "core";
2046
2181
  const roots = isPackagedRuntime()
2047
2182
  ? []
2048
- : [{ directory: packagePath("plugins"), defaultEnabled: true }];
2183
+ : !sourceCheckout
2184
+ ? [{ directory: packagePath("plugins"), defaultEnabled: true }]
2185
+ : (0, workspace_layout_cjs_1.sourcePlugins)(side, node_path_1.default.resolve(packagePath(), "../..")).map((plugin) => ({
2186
+ directory: plugin.directory,
2187
+ folder: plugin.folder,
2188
+ defaultEnabled: true
2189
+ }));
2049
2190
  // Project-installed npm plugins load in development too: they are dependencies
2050
2191
  // of the development project, not of the published runtime package.
2051
2192
  roots.push(...npmPluginRoots(side));
@@ -2066,7 +2207,7 @@ function bundledToolPath(name) {
2066
2207
  // Published daemon packages download native tools into the installation's
2067
2208
  // writable lib directory on first start. Development checkouts use the same
2068
2209
  // repository-local sibling of data and logs.
2069
- const root = isPackagedRuntime() ? node_path_1.default.resolve(process.cwd(), "lib") : packagePath("lib");
2210
+ const root = node_path_1.default.resolve(process.cwd(), "lib");
2070
2211
  const primary = node_path_1.default.join(root, filename);
2071
2212
  // Zip-Tools names its Intel macOS binary "amd64", while Node reports "x64".
2072
2213
  if (!node_fs_1.default.existsSync(primary) && name === "file_zip" && platform === "darwin" && arch === "x64") {
@@ -2094,6 +2235,7 @@ function ensureExecutable(filename) {
2094
2235
  /***/ "../common/src/string_utils.ts"
2095
2236
  (__unused_webpack_module, exports) {
2096
2237
 
2238
+ "use strict";
2097
2239
 
2098
2240
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2099
2241
  exports.removeTrail = removeTrail;
@@ -2112,6 +2254,7 @@ function removeTrail(origin, trail) {
2112
2254
  /***/ "../common/src/system_info.ts"
2113
2255
  (__unused_webpack_module, exports, __webpack_require__) {
2114
2256
 
2257
+ "use strict";
2115
2258
 
2116
2259
  var __importDefault = (this && this.__importDefault) || function (mod) {
2117
2260
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -2204,6 +2347,7 @@ function systemInfo() {
2204
2347
  /***/ "../common/src/system_storage.ts"
2205
2348
  (__unused_webpack_module, exports, __webpack_require__) {
2206
2349
 
2350
+ "use strict";
2207
2351
 
2208
2352
  var __importDefault = (this && this.__importDefault) || function (mod) {
2209
2353
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -2335,6 +2479,7 @@ exports["default"] = StorageSubsystem;
2335
2479
  /***/ "../common/src/typecheck.ts"
2336
2480
  (__unused_webpack_module, exports) {
2337
2481
 
2482
+ "use strict";
2338
2483
 
2339
2484
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2340
2485
  exports.configureEntityParams = configureEntityParams;
@@ -2409,113 +2554,12 @@ function supposeValue(v, def) {
2409
2554
  }
2410
2555
 
2411
2556
 
2412
- /***/ },
2413
-
2414
- /***/ "./plugins/config/src/backend/settings.ts"
2415
- (__unused_webpack_module, exports, __webpack_require__) {
2416
-
2417
-
2418
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2419
- exports.SettingsFormService = void 0;
2420
- const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
2421
- const cordis_1 = __webpack_require__("cordis");
2422
- const cosmokit_1 = __webpack_require__("cosmokit");
2423
- /** Configuration declarations are owned by the daemon config plugin. */
2424
- class SettingsFormService extends cordis_1.Service {
2425
- declarations = [];
2426
- constructor(ctx) {
2427
- super(ctx, "settingsForm", true);
2428
- }
2429
- declare(declaration) {
2430
- const entry = { id: this.ctx.name, declaration };
2431
- return this.ctx.effect(() => {
2432
- this.declarations.push(entry);
2433
- return () => (0, cosmokit_1.remove)(this.declarations, entry);
2434
- });
2435
- }
2436
- declared() {
2437
- return this.declarations.map((entry) => entry.id);
2438
- }
2439
- async read(id) {
2440
- const entry = this.declarations.find((item) => item.id === id);
2441
- if (!entry) {
2442
- const schema = this.ctx.plugins.configuration(id);
2443
- return schema.fields.length ? schema : null;
2444
- }
2445
- return { id, fields: entry.declaration.fields(), values: await entry.declaration.read() };
2446
- }
2447
- async write(id, values) {
2448
- const entry = this.declarations.find((item) => item.id === id);
2449
- if (!entry)
2450
- return (await this.ctx.plugins.configure(id, values)).result;
2451
- return this.ctx.plugins.runExclusive(async () => {
2452
- (0, mcsmanager_common_1.validatePluginSettings)(entry.declaration.fields(), values);
2453
- await entry.declaration.write(values);
2454
- return {
2455
- saved: true,
2456
- application: entry.declaration.restartRequired ? "restart-required" : "applied"
2457
- };
2458
- });
2459
- }
2460
- }
2461
- exports.SettingsFormService = SettingsFormService;
2462
-
2463
-
2464
- /***/ },
2465
-
2466
- /***/ "./plugins/config/src/i18n/index.ts"
2467
- (__unused_webpack_module, exports, __webpack_require__) {
2468
-
2469
-
2470
- var __importDefault = (this && this.__importDefault) || function (mod) {
2471
- return (mod && mod.__esModule) ? mod : { "default": mod };
2472
- };
2473
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2474
- exports.localeMessages = void 0;
2475
- const de_DE_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/de_DE.json"));
2476
- const en_US_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/en_US.json"));
2477
- const es_ES_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/es_ES.json"));
2478
- const fr_FR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/fr_FR.json"));
2479
- const ja_JP_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ja_JP.json"));
2480
- const ko_KR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ko_KR.json"));
2481
- const pt_BR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/pt_BR.json"));
2482
- const ru_RU_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ru_RU.json"));
2483
- const th_TH_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/th_TH.json"));
2484
- const tr_TR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/tr_TR.json"));
2485
- const zh_CN_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/zh_CN.json"));
2486
- const zh_TW_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/zh_TW.json"));
2487
- // The refusals this plugin's protocol handlers throw. The panel surfaces them
2488
- // verbatim on its plugin manager page, so they are translated here rather than
2489
- // in the panel: this daemon knows which of its own plugins may not be switched
2490
- // off remotely, and it answers in the language it was told to speak.
2491
- exports.localeMessages = {
2492
- de_de: de_DE_json_1.default,
2493
- en_us: en_US_json_1.default,
2494
- es_es: es_ES_json_1.default,
2495
- fr_fr: fr_FR_json_1.default,
2496
- ja_jp: ja_JP_json_1.default,
2497
- ko_kr: ko_KR_json_1.default,
2498
- pt_br: pt_BR_json_1.default,
2499
- ru_ru: ru_RU_json_1.default,
2500
- th_th: th_TH_json_1.default,
2501
- tr_tr: tr_TR_json_1.default,
2502
- zh_cn: zh_CN_json_1.default,
2503
- zh_tw: zh_TW_json_1.default
2504
- };
2505
-
2506
-
2507
- /***/ },
2508
-
2509
- /***/ "events"
2510
- (module) {
2511
-
2512
- module.exports = require("events");
2513
-
2514
2557
  /***/ },
2515
2558
 
2516
2559
  /***/ "fs-extra"
2517
2560
  (module) {
2518
2561
 
2562
+ "use strict";
2519
2563
  module.exports = require("fs-extra");
2520
2564
 
2521
2565
  /***/ },
@@ -2523,6 +2567,7 @@ module.exports = require("fs-extra");
2523
2567
  /***/ "iconv-lite"
2524
2568
  (module) {
2525
2569
 
2570
+ "use strict";
2526
2571
  module.exports = require("iconv-lite");
2527
2572
 
2528
2573
  /***/ },
@@ -2530,6 +2575,7 @@ module.exports = require("iconv-lite");
2530
2575
  /***/ "os-utils"
2531
2576
  (module) {
2532
2577
 
2578
+ "use strict";
2533
2579
  module.exports = require("os-utils");
2534
2580
 
2535
2581
  /***/ },
@@ -2537,6 +2583,7 @@ module.exports = require("os-utils");
2537
2583
  /***/ "cordis"
2538
2584
  (module) {
2539
2585
 
2586
+ "use strict";
2540
2587
  module.exports = require("cordis");
2541
2588
 
2542
2589
  /***/ },
@@ -2544,6 +2591,7 @@ module.exports = require("cordis");
2544
2591
  /***/ "cosmokit"
2545
2592
  (module) {
2546
2593
 
2594
+ "use strict";
2547
2595
  module.exports = require("cosmokit");
2548
2596
 
2549
2597
  /***/ },
@@ -2551,6 +2599,7 @@ module.exports = require("cosmokit");
2551
2599
  /***/ "child_process"
2552
2600
  (module) {
2553
2601
 
2602
+ "use strict";
2554
2603
  module.exports = require("child_process");
2555
2604
 
2556
2605
  /***/ },
@@ -2558,13 +2607,23 @@ module.exports = require("child_process");
2558
2607
  /***/ "crypto"
2559
2608
  (module) {
2560
2609
 
2610
+ "use strict";
2561
2611
  module.exports = require("crypto");
2562
2612
 
2563
2613
  /***/ },
2564
2614
 
2615
+ /***/ "events"
2616
+ (module) {
2617
+
2618
+ "use strict";
2619
+ module.exports = require("events");
2620
+
2621
+ /***/ },
2622
+
2565
2623
  /***/ "fs"
2566
2624
  (module) {
2567
2625
 
2626
+ "use strict";
2568
2627
  module.exports = require("fs");
2569
2628
 
2570
2629
  /***/ },
@@ -2572,6 +2631,7 @@ module.exports = require("fs");
2572
2631
  /***/ "module"
2573
2632
  (module) {
2574
2633
 
2634
+ "use strict";
2575
2635
  module.exports = require("module");
2576
2636
 
2577
2637
  /***/ },
@@ -2579,6 +2639,7 @@ module.exports = require("module");
2579
2639
  /***/ "net"
2580
2640
  (module) {
2581
2641
 
2642
+ "use strict";
2582
2643
  module.exports = require("net");
2583
2644
 
2584
2645
  /***/ },
@@ -2586,6 +2647,7 @@ module.exports = require("net");
2586
2647
  /***/ "node:crypto"
2587
2648
  (module) {
2588
2649
 
2650
+ "use strict";
2589
2651
  module.exports = require("node:crypto");
2590
2652
 
2591
2653
  /***/ },
@@ -2593,6 +2655,7 @@ module.exports = require("node:crypto");
2593
2655
  /***/ "node:fs"
2594
2656
  (module) {
2595
2657
 
2658
+ "use strict";
2596
2659
  module.exports = require("node:fs");
2597
2660
 
2598
2661
  /***/ },
@@ -2600,6 +2663,7 @@ module.exports = require("node:fs");
2600
2663
  /***/ "node:module"
2601
2664
  (module) {
2602
2665
 
2666
+ "use strict";
2603
2667
  module.exports = require("node:module");
2604
2668
 
2605
2669
  /***/ },
@@ -2607,6 +2671,7 @@ module.exports = require("node:module");
2607
2671
  /***/ "node:os"
2608
2672
  (module) {
2609
2673
 
2674
+ "use strict";
2610
2675
  module.exports = require("node:os");
2611
2676
 
2612
2677
  /***/ },
@@ -2614,6 +2679,7 @@ module.exports = require("node:os");
2614
2679
  /***/ "node:path"
2615
2680
  (module) {
2616
2681
 
2682
+ "use strict";
2617
2683
  module.exports = require("node:path");
2618
2684
 
2619
2685
  /***/ },
@@ -2621,6 +2687,7 @@ module.exports = require("node:path");
2621
2687
  /***/ "node:url"
2622
2688
  (module) {
2623
2689
 
2690
+ "use strict";
2624
2691
  module.exports = require("node:url");
2625
2692
 
2626
2693
  /***/ },
@@ -2628,6 +2695,7 @@ module.exports = require("node:url");
2628
2695
  /***/ "os"
2629
2696
  (module) {
2630
2697
 
2698
+ "use strict";
2631
2699
  module.exports = require("os");
2632
2700
 
2633
2701
  /***/ },
@@ -2635,6 +2703,7 @@ module.exports = require("os");
2635
2703
  /***/ "path"
2636
2704
  (module) {
2637
2705
 
2706
+ "use strict";
2638
2707
  module.exports = require("path");
2639
2708
 
2640
2709
  /***/ },
@@ -2642,90 +2711,157 @@ module.exports = require("path");
2642
2711
  /***/ "process"
2643
2712
  (module) {
2644
2713
 
2714
+ "use strict";
2645
2715
  module.exports = require("process");
2646
2716
 
2647
2717
  /***/ },
2648
2718
 
2649
- /***/ "./plugins/config/src/i18n/de_DE.json"
2719
+ /***/ "../../scripts/workspace-layout.cjs"
2720
+ (module, __unused_webpack_exports, __webpack_require__) {
2721
+
2722
+ const fs = __webpack_require__("node:fs");
2723
+ const path = __webpack_require__("node:path");
2724
+
2725
+ const repository = path.resolve(__dirname, "..");
2726
+ const coreDirectory = (side, root = repository) => path.join(root, "core", side);
2727
+ const developmentDirectory = (side, root = repository) => path.join(root, "data", side);
2728
+
2729
+ /** Source packages use the same per-side metadata as their published npm packages. */
2730
+ function sourcePlugins(side, root = repository) {
2731
+ if (!["panel", "daemon"].includes(side)) throw new Error(`Unknown plugin side: ${side}`);
2732
+ const directory = path.join(root, "plugins");
2733
+ if (!fs.existsSync(directory)) return [];
2734
+ const plugins = [];
2735
+ for (const item of fs.readdirSync(directory, { withFileTypes: true })) {
2736
+ if (!item.isDirectory()) continue;
2737
+ const packageRoot = path.join(directory, item.name);
2738
+ const filename = path.join(packageRoot, "package.json");
2739
+ if (!fs.existsSync(filename)) continue;
2740
+ const metadata = JSON.parse(fs.readFileSync(filename, "utf8"));
2741
+ const definition = metadata.elementspanel?.[side];
2742
+ if (!definition) continue;
2743
+ const id = metadata.elementspanel.id;
2744
+ if (typeof id !== "string" || typeof definition.directory !== "string")
2745
+ throw new Error(`Invalid ${side} plugin metadata: ${filename}`);
2746
+ const pluginDirectory = path.resolve(packageRoot, definition.directory);
2747
+ const relative = path.relative(packageRoot, pluginDirectory);
2748
+ if (
2749
+ !relative ||
2750
+ relative === ".." ||
2751
+ relative.startsWith(`..${path.sep}`) ||
2752
+ path.isAbsolute(relative)
2753
+ )
2754
+ throw new Error(`Plugin directory must stay inside its package: ${filename}`);
2755
+ if (!fs.existsSync(path.join(pluginDirectory, "plugin.json")))
2756
+ throw new Error(`Missing ${side} plugin manifest: ${pluginDirectory}`);
2757
+ plugins.push({
2758
+ id,
2759
+ folder: definition.folder || id,
2760
+ directory: pluginDirectory,
2761
+ packageRoot,
2762
+ metadata
2763
+ });
2764
+ }
2765
+ return plugins.sort((a, b) => a.id.localeCompare(b.id));
2766
+ }
2767
+
2768
+ module.exports = { repository, coreDirectory, developmentDirectory, sourcePlugins };
2769
+
2770
+
2771
+ /***/ },
2772
+
2773
+ /***/ "../../plugins/config/daemon/src/i18n/de_DE.json"
2650
2774
  (module) {
2651
2775
 
2776
+ "use strict";
2652
2777
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Der Webserver kann nicht aus der Ferne deaktiviert werden: Das Panel würde die Verbindung verlieren, über die es diesen Daemon verwaltet. Setze plugins.server.enabled auf dem Host in seiner data/plugin-overrides.json auf false.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"Eine Plugin-ID ist erforderlich.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"Die Plugin-Verwaltung kann sich nicht selbst deaktivieren: Das Panel würde die Events verlieren, mit denen es diesen Daemon verwaltet. Setze plugins.config.enabled auf dem Host in seiner data/plugin-overrides.json auf false."}');
2653
2778
 
2654
2779
  /***/ },
2655
2780
 
2656
- /***/ "./plugins/config/src/i18n/en_US.json"
2781
+ /***/ "../../plugins/config/daemon/src/i18n/en_US.json"
2657
2782
  (module) {
2658
2783
 
2784
+ "use strict";
2659
2785
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"The web server cannot be disabled remotely: the panel would lose the connection it manages this daemon over. Set plugins.server.enabled to false in its data/plugin-overrides.json on the host instead.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"A plugin id is required.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"Plugin management cannot disable itself: the panel would lose the events it administers this daemon with. Set plugins.config.enabled to false in its data/plugin-overrides.json on the host instead."}');
2660
2786
 
2661
2787
  /***/ },
2662
2788
 
2663
- /***/ "./plugins/config/src/i18n/es_ES.json"
2789
+ /***/ "../../plugins/config/daemon/src/i18n/es_ES.json"
2664
2790
  (module) {
2665
2791
 
2792
+ "use strict";
2666
2793
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"El servidor web no puede desactivarse de forma remota: el panel perdería la conexión con la que administra este demonio. Establece plugins.server.enabled en false en su data/plugin-overrides.json en el host.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"Se requiere un id de complemento.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"La gestión de complementos no puede desactivarse a sí misma: el panel perdería los eventos con los que administra este demonio. Establece plugins.config.enabled en false en su data/plugin-overrides.json en el host."}');
2667
2794
 
2668
2795
  /***/ },
2669
2796
 
2670
- /***/ "./plugins/config/src/i18n/fr_FR.json"
2797
+ /***/ "../../plugins/config/daemon/src/i18n/fr_FR.json"
2671
2798
  (module) {
2672
2799
 
2800
+ "use strict";
2673
2801
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Le serveur web ne peut pas être désactivé à distance : le panneau perdrait la connexion par laquelle il administre ce démon. Définissez plugins.server.enabled à false dans son data/plugin-overrides.json sur l hôte.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"Un identifiant d extension est requis.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"Le gestionnaire d extensions ne peut pas se désactiver lui-même : le panneau perdrait les événements par lesquels il administre ce démon. Définissez plugins.config.enabled à false dans son data/plugin-overrides.json sur l hôte."}');
2674
2802
 
2675
2803
  /***/ },
2676
2804
 
2677
- /***/ "./plugins/config/src/i18n/ja_JP.json"
2805
+ /***/ "../../plugins/config/daemon/src/i18n/ja_JP.json"
2678
2806
  (module) {
2679
2807
 
2808
+ "use strict";
2680
2809
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Web サーバーはリモートから無効にできません。パネルがこのデーモンを管理している接続を失います。ホスト上で data/plugin-overrides.json の plugins.server.enabled を false に設定してください。","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"プラグイン ID を指定してください。","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"プラグイン管理は自身を無効にできません。パネルがこのデーモンを管理しているイベントを失います。ホスト上で data/plugin-overrides.json の plugins.config.enabled を false に設定してください。"}');
2681
2810
 
2682
2811
  /***/ },
2683
2812
 
2684
- /***/ "./plugins/config/src/i18n/ko_KR.json"
2813
+ /***/ "../../plugins/config/daemon/src/i18n/ko_KR.json"
2685
2814
  (module) {
2686
2815
 
2816
+ "use strict";
2687
2817
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"웹 서버는 원격으로 비활성화할 수 없습니다. 패널이 이 데몬을 관리하는 연결을 잃게 됩니다. 호스트에서 data/plugin-overrides.json의 plugins.server.enabled 를 false 로 설정하세요.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"플러그인 ID가 필요합니다.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"플러그인 관리는 자신을 비활성화할 수 없습니다. 패널이 이 데몬을 관리하는 이벤트를 잃게 됩니다. 호스트에서 data/plugin-overrides.json의 plugins.config.enabled 를 false 로 설정하세요."}');
2688
2818
 
2689
2819
  /***/ },
2690
2820
 
2691
- /***/ "./plugins/config/src/i18n/pt_BR.json"
2821
+ /***/ "../../plugins/config/daemon/src/i18n/pt_BR.json"
2692
2822
  (module) {
2693
2823
 
2824
+ "use strict";
2694
2825
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"O servidor web não pode ser desativado remotamente: o painel perderia a conexão pela qual administra este daemon. Defina plugins.server.enabled como false no data/plugin-overrides.json dele no host.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"É necessário informar o id do plugin.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"O gerenciador de plugins não pode desativar a si mesmo: o painel perderia os eventos pelos quais administra este daemon. Defina plugins.config.enabled como false no data/plugin-overrides.json dele no host."}');
2695
2826
 
2696
2827
  /***/ },
2697
2828
 
2698
- /***/ "./plugins/config/src/i18n/ru_RU.json"
2829
+ /***/ "../../plugins/config/daemon/src/i18n/ru_RU.json"
2699
2830
  (module) {
2700
2831
 
2832
+ "use strict";
2701
2833
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Веб-сервер нельзя отключить удалённо: панель потеряет соединение, через которое управляет этим демоном. Укажите plugins.server.enabled: false в его data/plugin-overrides.json на хосте.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"Требуется идентификатор плагина.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"Менеджер плагинов не может отключить сам себя: панель потеряет события, через которые управляет этим демоном. Укажите plugins.config.enabled: false в его data/plugin-overrides.json на хосте."}');
2702
2834
 
2703
2835
  /***/ },
2704
2836
 
2705
- /***/ "./plugins/config/src/i18n/th_TH.json"
2837
+ /***/ "../../plugins/config/daemon/src/i18n/th_TH.json"
2706
2838
  (module) {
2707
2839
 
2840
+ "use strict";
2708
2841
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"ไม่สามารถปิดใช้งานเว็บเซิร์ฟเวอร์จากระยะไกลได้ แผงควบคุมจะเสียการเชื่อมต่อที่ใช้จัดการดีมอนนี้ กรุณาตั้ง plugins.server.enabled เป็น false ใน data/plugin-overrides.json ของมันบนเครื่องโฮสต์","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"ต้องระบุรหัสปลั๊กอิน","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"ตัวจัดการปลั๊กอินปิดใช้งานตัวเองไม่ได้ แผงควบคุมจะเสียอีเวนต์ที่ใช้จัดการดีมอนนี้ กรุณาตั้ง plugins.config.enabled เป็น false ใน data/plugin-overrides.json ของมันบนเครื่องโฮสต์"}');
2709
2842
 
2710
2843
  /***/ },
2711
2844
 
2712
- /***/ "./plugins/config/src/i18n/tr_TR.json"
2845
+ /***/ "../../plugins/config/daemon/src/i18n/tr_TR.json"
2713
2846
  (module) {
2714
2847
 
2848
+ "use strict";
2715
2849
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Web sunucusu uzaktan devre dışı bırakılamaz: panel bu daemon u yönettiği bağlantıyı kaybeder. Bunun yerine ana makinede data/plugin-overrides.json dosyasında plugins.server.enabled değerini false yapın.","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"Bir eklenti kimliği gerekli.","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"Eklenti yöneticisi kendisini devre dışı bırakamaz: panel bu daemon u yönettiği olayları kaybeder. Bunun yerine ana makinede data/plugin-overrides.json dosyasında plugins.config.enabled değerini false yapın."}');
2716
2850
 
2717
2851
  /***/ },
2718
2852
 
2719
- /***/ "./plugins/config/src/i18n/zh_CN.json"
2853
+ /***/ "../../plugins/config/daemon/src/i18n/zh_CN.json"
2720
2854
  (module) {
2721
2855
 
2856
+ "use strict";
2722
2857
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Web 服务器不能远程禁用:面板会失去用来管理这个守护进程的连接。请在宿主机上把它的 data/plugin-overrides.json 里的 plugins.server.enabled 设为 false。","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"必须提供插件 ID。","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"插件管理无法禁用自己:面板会失去用来管理这个守护进程的事件。请在宿主机上把它的 data/plugin-overrides.json 里的 plugins.config.enabled 设为 false。"}');
2723
2858
 
2724
2859
  /***/ },
2725
2860
 
2726
- /***/ "./plugins/config/src/i18n/zh_TW.json"
2861
+ /***/ "../../plugins/config/daemon/src/i18n/zh_TW.json"
2727
2862
  (module) {
2728
2863
 
2864
+ "use strict";
2729
2865
  module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DISABLE":"Web 伺服器不能遠端停用:面板會失去用來管理這個守護行程的連線。請在主機上把它的 data/plugin-overrides.json 裡的 plugins.server.enabled 設為 false。","TXT_CODE_DAEMON_PLUGIN_ID_REQUIRED":"必須提供外掛 ID。","TXT_CODE_DAEMON_PLUGIN_SELF_DISABLE":"外掛管理無法停用自己:面板會失去用來管理這個守護行程的事件。請在主機上把它的 data/plugin-overrides.json 裡的 plugins.config.enabled 設為 false。"}');
2730
2866
 
2731
2867
  /***/ }
@@ -2758,16 +2894,18 @@ module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DIS
2758
2894
  /******/
2759
2895
  /************************************************************************/
2760
2896
  var __webpack_exports__ = {};
2761
- // This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
2897
+ // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
2762
2898
  (() => {
2899
+ "use strict";
2763
2900
  var exports = __webpack_exports__;
2764
2901
 
2765
2902
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2766
2903
  exports.inject = void 0;
2767
2904
  exports.apply = apply;
2768
2905
  const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
2769
- const i18n_1 = __webpack_require__("./plugins/config/src/i18n/index.ts");
2770
- const settings_1 = __webpack_require__("./plugins/config/src/backend/settings.ts");
2906
+ const i18n_1 = __webpack_require__("../../plugins/config/daemon/src/i18n/index.ts");
2907
+ const settings_1 = __webpack_require__("../../plugins/config/daemon/src/backend/settings.ts");
2908
+ const mcsmanager_common_2 = __webpack_require__("../common/src/index.ts");
2771
2909
  // Daemon side of the plugin manager. The daemon core owns the mechanism —
2772
2910
  // `ctx.plugins` lists what is installed and persists the enable switch — and
2773
2911
  // this plugin only exposes it over the protocol, because the panel's plugin
@@ -2884,23 +3022,61 @@ function apply(ctx) {
2884
3022
  // installation project. npm runs on the machine that will load the plugin, so
2885
3023
  // the panel only names the package and the version.
2886
3024
  ctx.protocol.on("plugin/npm/install", async (routerCtx, data) => {
3025
+ const protocol = ctx.protocol;
3026
+ let resume;
3027
+ const reloadAfter = new Promise((resolve) => {
3028
+ resume = resolve;
3029
+ });
3030
+ let respond;
2887
3031
  try {
2888
3032
  const payload = (data ?? {});
2889
3033
  const record = await ctx.plugins.install({
2890
3034
  name: String(payload.name ?? ""),
2891
3035
  pluginId: payload.pluginId ? String(payload.pluginId) : undefined,
2892
- version: payload.version ? String(payload.version) : undefined
3036
+ version: payload.version ? String(payload.version) : undefined,
3037
+ reloadAfter
2893
3038
  });
2894
- ctx.protocol.response(routerCtx, record);
3039
+ respond = () => protocol.response(routerCtx, record);
2895
3040
  }
2896
3041
  catch (error) {
2897
- ctx.protocol.responseError(routerCtx, error);
3042
+ respond = () => protocol.responseError(routerCtx, error);
3043
+ }
3044
+ const connection = routerCtx.socket?.conn;
3045
+ let flushed = false;
3046
+ const onDrain = () => {
3047
+ flushed = true;
3048
+ };
3049
+ connection?.once("drain", onDrain);
3050
+ try {
3051
+ respond();
3052
+ }
3053
+ finally {
3054
+ // A polling transport may be between HTTP requests. Wait until Engine.IO
3055
+ // hands the buffered reply to its transport before replacing the socket.
3056
+ connection?.off("drain", onDrain);
3057
+ if (connection?.readyState === "open" && !flushed) {
3058
+ const release = () => {
3059
+ clearTimeout(timeout);
3060
+ connection.off("drain", release);
3061
+ connection.off("close", release);
3062
+ setImmediate(resume);
3063
+ };
3064
+ const timeout = setTimeout(release, 10000);
3065
+ connection.once("drain", release);
3066
+ connection.once("close", release);
3067
+ }
3068
+ else {
3069
+ setImmediate(resume);
3070
+ }
2898
3071
  }
2899
3072
  });
2900
3073
  ctx.protocol.on("plugin/npm/uninstall", async (routerCtx, data) => {
2901
3074
  try {
2902
3075
  const pluginId = String(data?.pluginId ?? "");
2903
3076
  await ctx.plugins.remove(pluginId);
3077
+ if (data?.removeConfig === true) {
3078
+ await ctx.plugins.runExclusive(async () => (0, mcsmanager_common_2.writePluginOverride)(pluginId, { config: {} }));
3079
+ }
2904
3080
  ctx.protocol.response(routerCtx, { removed: true, pluginId });
2905
3081
  }
2906
3082
  catch (error) {