@elementspanel/epanel-plugin-config 1.0.0 → 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/README.md +1 -5
- package/daemon/backend/index.cjs +856 -212
- package/daemon/plugin.json +0 -6
- package/package.json +17 -4
- package/panel/backend/index.cjs +4010 -229
- package/panel/frontend/assets/style-0-_panel-plugin-build-entry_config-f6a935f2.css +1 -0
- package/panel/frontend/panel-plugin-config-106e7df7.js +1 -0
- package/panel/plugin.json +1 -13
- package/panel/frontend/assets/style-0-_panel-plugin-build-entry_config-4aa69b22.css +0 -1
- package/panel/frontend/panel-plugin-config-cb428381.js +0 -1
package/daemon/backend/index.cjs
CHANGED
|
@@ -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;
|
|
@@ -109,7 +209,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
109
209
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
110
210
|
};
|
|
111
211
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
112
|
-
exports.StorageSubsystem = exports.MCServerStatus = exports.InstanceStreamListener = exports.GlobalVariable = exports.normalizeDockerPlatform = exports.normalizeDockerOS = exports.normalizeDockerArchitecture = exports.removeTrail = exports.uninstallNpmPlugin = exports.npmPluginRoots = exports.listNpmPlugins = exports.installNpmPlugin = exports.currentProjectRoot = exports.currentPackageRoot = exports.sortPlugins = exports.resolvePluginEntry = exports.readPluginManifest = exports.createFrontendPluginMetadata = exports.discoverPluginsFromRoots = exports.discoverPlugins = exports.arrayUnique = exports.toText = exports.toNumber = exports.toBoolean = exports.supposeValue = exports.isEmpty = exports.configureEntityParams = exports.systemInfo = exports.QueryWrapper = exports.QueryMapWrapper = exports.MySqlSource = exports.LocalFileSource = exports.killProcess = exports.ProcessWrapper = void 0;
|
|
212
|
+
exports.StorageSubsystem = exports.MCServerStatus = exports.InstanceStreamListener = exports.GlobalVariable = exports.normalizeDockerPlatform = exports.normalizeDockerOS = exports.normalizeDockerArchitecture = exports.removeTrail = exports.uninstallNpmPlugin = exports.isEssentialNpmPlugin = exports.npmPluginOperationPending = exports.npmPluginRoots = exports.listNpmPlugins = exports.installNpmPlugin = exports.currentProjectRoot = exports.currentPackageRoot = exports.sortPlugins = exports.resolvePluginEntry = exports.readPluginManifest = exports.createFrontendPluginMetadata = exports.discoverPluginsFromRoots = exports.discoverPlugins = exports.arrayUnique = exports.toText = exports.toNumber = exports.toBoolean = exports.supposeValue = exports.isEmpty = exports.configureEntityParams = exports.systemInfo = exports.QueryWrapper = exports.QueryMapWrapper = exports.MySqlSource = exports.LocalFileSource = exports.killProcess = exports.ProcessWrapper = void 0;
|
|
113
213
|
const global_variable_1 = __importDefault(__webpack_require__("../common/src/global_variable.ts"));
|
|
114
214
|
exports.GlobalVariable = global_variable_1.default;
|
|
115
215
|
const instance_stream_1 = __importDefault(__webpack_require__("../common/src/instance_stream.ts"));
|
|
@@ -141,6 +241,8 @@ __exportStar(__webpack_require__("../common/src/plugin_contract.ts"), exports);
|
|
|
141
241
|
__exportStar(__webpack_require__("../common/src/plugin_overrides.ts"), exports);
|
|
142
242
|
__exportStar(__webpack_require__("../common/src/plugin_lifecycle.ts"), exports);
|
|
143
243
|
__exportStar(__webpack_require__("../common/src/plugin_revision.ts"), exports);
|
|
244
|
+
__exportStar(__webpack_require__("../common/src/plugin_modules.ts"), exports);
|
|
245
|
+
__exportStar(__webpack_require__("../common/src/plugin_watch.ts"), exports);
|
|
144
246
|
__exportStar(__webpack_require__("../common/src/runtime_paths.ts"), exports);
|
|
145
247
|
var plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
146
248
|
Object.defineProperty(exports, "discoverPlugins", ({ enumerable: true, get: function () { return plugin_manifest_1.discoverPlugins; } }));
|
|
@@ -155,6 +257,8 @@ Object.defineProperty(exports, "currentProjectRoot", ({ enumerable: true, get: f
|
|
|
155
257
|
Object.defineProperty(exports, "installNpmPlugin", ({ enumerable: true, get: function () { return plugin_npm_1.installNpmPlugin; } }));
|
|
156
258
|
Object.defineProperty(exports, "listNpmPlugins", ({ enumerable: true, get: function () { return plugin_npm_1.listNpmPlugins; } }));
|
|
157
259
|
Object.defineProperty(exports, "npmPluginRoots", ({ enumerable: true, get: function () { return plugin_npm_1.npmPluginRoots; } }));
|
|
260
|
+
Object.defineProperty(exports, "npmPluginOperationPending", ({ enumerable: true, get: function () { return plugin_npm_1.npmPluginOperationPending; } }));
|
|
261
|
+
Object.defineProperty(exports, "isEssentialNpmPlugin", ({ enumerable: true, get: function () { return plugin_npm_1.isEssentialNpmPlugin; } }));
|
|
158
262
|
Object.defineProperty(exports, "uninstallNpmPlugin", ({ enumerable: true, get: function () { return plugin_npm_1.uninstallNpmPlugin; } }));
|
|
159
263
|
var string_utils_1 = __webpack_require__("../common/src/string_utils.ts");
|
|
160
264
|
Object.defineProperty(exports, "removeTrail", ({ enumerable: true, get: function () { return string_utils_1.removeTrail; } }));
|
|
@@ -169,6 +273,7 @@ Object.defineProperty(exports, "normalizeDockerPlatform", ({ enumerable: true, g
|
|
|
169
273
|
/***/ "../common/src/instance_stream.ts"
|
|
170
274
|
(__unused_webpack_module, exports) {
|
|
171
275
|
|
|
276
|
+
"use strict";
|
|
172
277
|
|
|
173
278
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
174
279
|
// Application instance data stream forwarding adapter
|
|
@@ -228,6 +333,7 @@ exports["default"] = InstanceStreamListener;
|
|
|
228
333
|
/***/ "../common/src/mcping.ts"
|
|
229
334
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
230
335
|
|
|
336
|
+
"use strict";
|
|
231
337
|
|
|
232
338
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
233
339
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -346,6 +452,7 @@ exports["default"] = PingMinecraftServer;
|
|
|
346
452
|
/***/ "../common/src/plugin_contract.ts"
|
|
347
453
|
(__unused_webpack_module, exports) {
|
|
348
454
|
|
|
455
|
+
"use strict";
|
|
349
456
|
|
|
350
457
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
351
458
|
exports.PLUGIN_SDK_VERSION = exports.PLUGIN_API_VERSION = void 0;
|
|
@@ -512,6 +619,7 @@ function validatePluginSettings(fields, values) {
|
|
|
512
619
|
/***/ "../common/src/plugin_lifecycle.ts"
|
|
513
620
|
(__unused_webpack_module, exports) {
|
|
514
621
|
|
|
622
|
+
"use strict";
|
|
515
623
|
|
|
516
624
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
517
625
|
exports.trackPluginDisposal = trackPluginDisposal;
|
|
@@ -578,6 +686,7 @@ function trackPluginDisposal(ctx) {
|
|
|
578
686
|
/***/ "../common/src/plugin_manifest.ts"
|
|
579
687
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
580
688
|
|
|
689
|
+
"use strict";
|
|
581
690
|
|
|
582
691
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
583
692
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -622,7 +731,52 @@ function createFrontendPluginMetadata(manifest, extras = {}) {
|
|
|
622
731
|
};
|
|
623
732
|
}
|
|
624
733
|
const MANIFEST_FILES = ["plugin.json", "manifest.json", "package.json"];
|
|
625
|
-
|
|
734
|
+
const ENTRY_FIELDS = ["backend", "frontend", "panel", "daemon", "main", "entry", "ui"];
|
|
735
|
+
function objectValue(value) {
|
|
736
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
737
|
+
? value
|
|
738
|
+
: {};
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Source plugins keep package.json beside plugin.json. Published npm plugins
|
|
742
|
+
* keep it at the package root, with runtime metadata under elementspanel.<side>.
|
|
743
|
+
* Stop at the first package boundary so a host's metadata cannot reach a plugin.
|
|
744
|
+
*/
|
|
745
|
+
function readPackageMetadata(directory) {
|
|
746
|
+
const pluginDirectory = node_path_1.default.resolve(directory);
|
|
747
|
+
let current = pluginDirectory;
|
|
748
|
+
while (true) {
|
|
749
|
+
const filename = node_path_1.default.join(current, "package.json");
|
|
750
|
+
if (node_fs_1.default.existsSync(filename)) {
|
|
751
|
+
const { elementspanel, ...metadata } = objectValue(JSON.parse(node_fs_1.default.readFileSync(filename, "utf8")));
|
|
752
|
+
const { id: packageId, panel, daemon, ...shared } = objectValue(elementspanel);
|
|
753
|
+
const definition = [panel, daemon]
|
|
754
|
+
.map(objectValue)
|
|
755
|
+
.find((side) => typeof side.directory === "string" &&
|
|
756
|
+
node_path_1.default.resolve(current, side.directory) === pluginDirectory);
|
|
757
|
+
if (current !== pluginDirectory && (typeof packageId !== "string" || !definition))
|
|
758
|
+
return {};
|
|
759
|
+
const { directory: _directory, folder: _folder, ...sideMetadata } = definition ?? {};
|
|
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;
|
|
768
|
+
// npm's main/entry fields do not define a side's execution entry.
|
|
769
|
+
for (const field of ENTRY_FIELDS)
|
|
770
|
+
delete result[field];
|
|
771
|
+
return result;
|
|
772
|
+
}
|
|
773
|
+
const parent = node_path_1.default.dirname(current);
|
|
774
|
+
if (parent === current)
|
|
775
|
+
return {};
|
|
776
|
+
current = parent;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/** Combines execution entries with package metadata. Legacy manifests still load. */
|
|
626
780
|
function readPluginManifest(directory, onWarning, fallbackId = node_path_1.default.basename(directory)) {
|
|
627
781
|
for (const file of MANIFEST_FILES) {
|
|
628
782
|
const filePath = node_path_1.default.join(directory, file);
|
|
@@ -632,10 +786,26 @@ function readPluginManifest(directory, onWarning, fallbackId = node_path_1.defau
|
|
|
632
786
|
const value = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
|
|
633
787
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
634
788
|
return null;
|
|
635
|
-
const
|
|
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;
|
|
636
795
|
if (!id.trim())
|
|
637
796
|
return null;
|
|
638
|
-
|
|
797
|
+
const manifest = {
|
|
798
|
+
...value,
|
|
799
|
+
...packageMetadata,
|
|
800
|
+
id: id.trim()
|
|
801
|
+
};
|
|
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) {
|
|
805
|
+
if (value[field] !== undefined)
|
|
806
|
+
manifest[field] = value[field];
|
|
807
|
+
}
|
|
808
|
+
return manifest;
|
|
639
809
|
}
|
|
640
810
|
catch (error) {
|
|
641
811
|
onWarning?.(`Failed to read plugin manifest: ${filePath}`, error);
|
|
@@ -733,6 +903,13 @@ function discoverPluginsFromRoots(roots, options) {
|
|
|
733
903
|
discovered.push({
|
|
734
904
|
...plugin,
|
|
735
905
|
manifest,
|
|
906
|
+
...(root.packageRoot
|
|
907
|
+
? {
|
|
908
|
+
packageRoot: root.packageRoot,
|
|
909
|
+
packageName: root.packageName,
|
|
910
|
+
npmSource: root.npmSource
|
|
911
|
+
}
|
|
912
|
+
: {}),
|
|
736
913
|
...(root.folder ? { folder: root.folder } : {})
|
|
737
914
|
});
|
|
738
915
|
}
|
|
@@ -746,11 +923,184 @@ function sortPlugins(plugins) {
|
|
|
746
923
|
}
|
|
747
924
|
|
|
748
925
|
|
|
926
|
+
/***/ },
|
|
927
|
+
|
|
928
|
+
/***/ "../common/src/plugin_modules.ts"
|
|
929
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
930
|
+
|
|
931
|
+
"use strict";
|
|
932
|
+
|
|
933
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
934
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
935
|
+
};
|
|
936
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
937
|
+
exports.pluginBackendRevision = pluginBackendRevision;
|
|
938
|
+
exports.forgetPluginModules = forgetPluginModules;
|
|
939
|
+
exports.loadPluginModule = loadPluginModule;
|
|
940
|
+
const node_fs_1 = __importDefault(__webpack_require__("node:fs"));
|
|
941
|
+
const node_path_1 = __importDefault(__webpack_require__("node:path"));
|
|
942
|
+
const node_url_1 = __webpack_require__("node:url");
|
|
943
|
+
const node_crypto_1 = __webpack_require__("node:crypto");
|
|
944
|
+
const node_module_1 = __webpack_require__("node:module");
|
|
945
|
+
const plugin_revision_1 = __webpack_require__("../common/src/plugin_revision.ts");
|
|
946
|
+
const REVISION = "epanelPluginRevision";
|
|
947
|
+
const graphs = new Map();
|
|
948
|
+
const previousRoots = new Map();
|
|
949
|
+
let hooksInstalled = false;
|
|
950
|
+
const sharedModules = new Set([
|
|
951
|
+
"cordis",
|
|
952
|
+
"@cordisjs/core",
|
|
953
|
+
"@cordisjs/logger",
|
|
954
|
+
"@cordisjs/timer",
|
|
955
|
+
"@cordisjs/schema",
|
|
956
|
+
"cosmokit",
|
|
957
|
+
"schemastery",
|
|
958
|
+
"reggol"
|
|
959
|
+
]);
|
|
960
|
+
function dependencyRoots(directory) {
|
|
961
|
+
const visited = new Set([directory]);
|
|
962
|
+
const walk = (root) => {
|
|
963
|
+
const filename = node_path_1.default.join(root, "package.json");
|
|
964
|
+
if (!node_fs_1.default.existsSync(filename))
|
|
965
|
+
return;
|
|
966
|
+
const metadata = JSON.parse(node_fs_1.default.readFileSync(filename, "utf8"));
|
|
967
|
+
const localRequire = (0, node_module_1.createRequire)(filename);
|
|
968
|
+
for (const name of Object.keys({
|
|
969
|
+
...metadata.dependencies,
|
|
970
|
+
...metadata.optionalDependencies
|
|
971
|
+
})) {
|
|
972
|
+
if (sharedModules.has(name))
|
|
973
|
+
continue;
|
|
974
|
+
const target = (localRequire.resolve.paths(name) || [])
|
|
975
|
+
.map((directory) => node_path_1.default.join(directory, name, "package.json"))
|
|
976
|
+
.find((candidate) => node_fs_1.default.existsSync(candidate));
|
|
977
|
+
if (!target)
|
|
978
|
+
continue;
|
|
979
|
+
const dependency = node_fs_1.default.realpathSync(node_path_1.default.dirname(target));
|
|
980
|
+
if (visited.has(dependency))
|
|
981
|
+
continue;
|
|
982
|
+
visited.add(dependency);
|
|
983
|
+
walk(dependency);
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
walk(directory);
|
|
987
|
+
visited.delete(directory);
|
|
988
|
+
return [...visited];
|
|
989
|
+
}
|
|
990
|
+
/** Include transitive dependency versions so npm updates replace the affected graph. */
|
|
991
|
+
function pluginBackendRevision(entry, directory) {
|
|
992
|
+
const hash = (0, node_crypto_1.createHash)("sha256").update((0, plugin_revision_1.pluginDirectoryRevision)(node_path_1.default.dirname(entry)));
|
|
993
|
+
for (const root of [directory, ...dependencyRoots(directory)]) {
|
|
994
|
+
const filename = node_path_1.default.join(root, "package.json");
|
|
995
|
+
if (node_fs_1.default.existsSync(filename))
|
|
996
|
+
hash.update(root).update(node_fs_1.default.readFileSync(filename));
|
|
997
|
+
}
|
|
998
|
+
return hash.digest("hex").slice(0, 24);
|
|
999
|
+
}
|
|
1000
|
+
function within(root, filename) {
|
|
1001
|
+
const relative = node_path_1.default.relative(root, filename);
|
|
1002
|
+
return (relative === "" ||
|
|
1003
|
+
(!relative.startsWith(`..${node_path_1.default.sep}`) && relative !== ".." && !node_path_1.default.isAbsolute(relative)));
|
|
1004
|
+
}
|
|
1005
|
+
/** Clear the plugin's complete CJS graph, keeping shared host modules intact. */
|
|
1006
|
+
function forgetPluginModules(directory) {
|
|
1007
|
+
const runtimeRequire = eval("require");
|
|
1008
|
+
const owned = [directory, ...(previousRoots.get(directory) || []), ...dependencyRoots(directory)];
|
|
1009
|
+
previousRoots.delete(directory);
|
|
1010
|
+
const belongs = (filename) => {
|
|
1011
|
+
const parts = filename.split(`${node_path_1.default.sep}node_modules${node_path_1.default.sep}`);
|
|
1012
|
+
if (parts.slice(1).some((part) => {
|
|
1013
|
+
const name = part.startsWith("@")
|
|
1014
|
+
? part.split(node_path_1.default.sep).slice(0, 2).join("/")
|
|
1015
|
+
: part.split(node_path_1.default.sep)[0];
|
|
1016
|
+
return sharedModules.has(name);
|
|
1017
|
+
}))
|
|
1018
|
+
return false;
|
|
1019
|
+
return owned.some((root) => within(root, filename));
|
|
1020
|
+
};
|
|
1021
|
+
for (const filename of Object.keys(runtimeRequire.cache)) {
|
|
1022
|
+
if (belongs(filename))
|
|
1023
|
+
delete runtimeRequire.cache[filename];
|
|
1024
|
+
}
|
|
1025
|
+
for (const mod of Object.values(runtimeRequire.cache)) {
|
|
1026
|
+
if (mod)
|
|
1027
|
+
mod.children = mod.children.filter((child) => !belongs(child.filename));
|
|
1028
|
+
}
|
|
1029
|
+
// npm can move a dependency or change its main entry. Node's CJS resolver
|
|
1030
|
+
// retains those paths separately from require.cache.
|
|
1031
|
+
const pathCache = runtimeRequire("node:module")._pathCache;
|
|
1032
|
+
for (const [key, filename] of Object.entries(pathCache)) {
|
|
1033
|
+
if (belongs(filename) || owned.some((root) => key.includes(root)))
|
|
1034
|
+
delete pathCache[key];
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
function isEsm(entry) {
|
|
1038
|
+
if (entry.endsWith(".mjs"))
|
|
1039
|
+
return true;
|
|
1040
|
+
if (entry.endsWith(".cjs"))
|
|
1041
|
+
return false;
|
|
1042
|
+
let directory = node_path_1.default.dirname(entry);
|
|
1043
|
+
while (true) {
|
|
1044
|
+
const filename = node_path_1.default.join(directory, "package.json");
|
|
1045
|
+
if (node_fs_1.default.existsSync(filename))
|
|
1046
|
+
return JSON.parse(node_fs_1.default.readFileSync(filename, "utf8")).type === "module";
|
|
1047
|
+
const parent = node_path_1.default.dirname(directory);
|
|
1048
|
+
if (parent === directory)
|
|
1049
|
+
return false;
|
|
1050
|
+
directory = parent;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
/** Give an ESM entry and its local imports the same immutable revision URL. */
|
|
1054
|
+
async function loadPluginModule(entry, directory, revision) {
|
|
1055
|
+
const runtimeRequire = eval("require");
|
|
1056
|
+
previousRoots.set(directory, dependencyRoots(directory));
|
|
1057
|
+
if (!isEsm(entry)) {
|
|
1058
|
+
try {
|
|
1059
|
+
return runtimeRequire(entry);
|
|
1060
|
+
}
|
|
1061
|
+
catch (error) {
|
|
1062
|
+
if (error?.code !== "ERR_REQUIRE_ESM")
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
graphs.set(revision, [directory, ...dependencyRoots(directory)]);
|
|
1067
|
+
if (!hooksInstalled) {
|
|
1068
|
+
const { registerHooks } = runtimeRequire("node:module");
|
|
1069
|
+
if (typeof registerHooks !== "function")
|
|
1070
|
+
throw new Error("ESM plugin updates require Node.js 22.15 or newer.");
|
|
1071
|
+
registerHooks({
|
|
1072
|
+
resolve(specifier, context, nextResolve) {
|
|
1073
|
+
const resolved = nextResolve(specifier, context);
|
|
1074
|
+
if (!context.parentURL?.startsWith("file:") || !resolved.url.startsWith("file:"))
|
|
1075
|
+
return resolved;
|
|
1076
|
+
const parent = new URL(context.parentURL);
|
|
1077
|
+
const parentRevision = parent.searchParams.get(REVISION);
|
|
1078
|
+
if (!parentRevision)
|
|
1079
|
+
return resolved;
|
|
1080
|
+
const roots = graphs.get(parentRevision);
|
|
1081
|
+
if (!roots?.some((root) => within(root, (0, node_url_1.fileURLToPath)(parent))) ||
|
|
1082
|
+
!roots.some((root) => within(root, (0, node_url_1.fileURLToPath)(resolved.url))))
|
|
1083
|
+
return resolved;
|
|
1084
|
+
const url = new URL(resolved.url);
|
|
1085
|
+
url.searchParams.set(REVISION, parentRevision);
|
|
1086
|
+
return { ...resolved, url: url.href };
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
hooksInstalled = true;
|
|
1090
|
+
}
|
|
1091
|
+
const url = (0, node_url_1.pathToFileURL)(entry);
|
|
1092
|
+
url.searchParams.set(REVISION, revision);
|
|
1093
|
+
const dynamicImport = new Function("specifier", "return import(specifier)");
|
|
1094
|
+
return dynamicImport(url.href);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
|
|
749
1098
|
/***/ },
|
|
750
1099
|
|
|
751
1100
|
/***/ "../common/src/plugin_npm.ts"
|
|
752
1101
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
753
1102
|
|
|
1103
|
+
"use strict";
|
|
754
1104
|
|
|
755
1105
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
756
1106
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -760,15 +1110,19 @@ exports.currentPackageRoot = currentPackageRoot;
|
|
|
760
1110
|
exports.currentProjectRoot = currentProjectRoot;
|
|
761
1111
|
exports.npmPluginRoots = npmPluginRoots;
|
|
762
1112
|
exports.listNpmPlugins = listNpmPlugins;
|
|
1113
|
+
exports.npmPluginOperationPending = npmPluginOperationPending;
|
|
1114
|
+
exports.isEssentialNpmPlugin = isEssentialNpmPlugin;
|
|
763
1115
|
exports.installNpmPlugin = installNpmPlugin;
|
|
764
1116
|
exports.uninstallNpmPlugin = uninstallNpmPlugin;
|
|
765
1117
|
const child_process_1 = __webpack_require__("child_process");
|
|
766
1118
|
const fs_extra_1 = __importDefault(__webpack_require__("fs-extra"));
|
|
767
1119
|
const path_1 = __importDefault(__webpack_require__("path"));
|
|
768
1120
|
const module_1 = __webpack_require__("module");
|
|
1121
|
+
const plugin_manifest_1 = __webpack_require__("../common/src/plugin_manifest.ts");
|
|
1122
|
+
const plugin_contract_1 = __webpack_require__("../common/src/plugin_contract.ts");
|
|
769
1123
|
const PLUGIN_ID = /^[a-z][a-z0-9_-]{1,63}$/;
|
|
770
1124
|
const PACKAGE_NAME = /^(?:@[a-z0-9_.-]+\/)?epanel-plugin-[a-z0-9_.-]+$/;
|
|
771
|
-
const VERSION = /^[
|
|
1125
|
+
const VERSION = /^[a-zA-Z0-9][a-zA-Z0-9._+-]{0,63}$/;
|
|
772
1126
|
function readJson(filename) {
|
|
773
1127
|
try {
|
|
774
1128
|
const parsed = JSON.parse(fs_extra_1.default.readFileSync(filename, "utf8"));
|
|
@@ -791,7 +1145,7 @@ function stringValue(value) {
|
|
|
791
1145
|
return typeof value === "string" ? value : "";
|
|
792
1146
|
}
|
|
793
1147
|
function currentPackageRoot() {
|
|
794
|
-
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());
|
|
795
1149
|
}
|
|
796
1150
|
function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
797
1151
|
// The npm worker sets EPANEL_PROJECT_ROOT to the installation directory. In a
|
|
@@ -799,6 +1153,8 @@ function currentProjectRoot(packageRoot = currentPackageRoot()) {
|
|
|
799
1153
|
if (process.env.EPANEL_PROJECT_ROOT)
|
|
800
1154
|
return path_1.default.resolve(process.env.EPANEL_PROJECT_ROOT);
|
|
801
1155
|
const scope = path_1.default.resolve(packageRoot, "..");
|
|
1156
|
+
if (path_1.default.basename(scope) === "core")
|
|
1157
|
+
return path_1.default.dirname(scope);
|
|
802
1158
|
const nodeModules = path_1.default.dirname(scope);
|
|
803
1159
|
if (path_1.default.basename(nodeModules) === "node_modules" && path_1.default.basename(scope).startsWith("@"))
|
|
804
1160
|
return path_1.default.dirname(nodeModules);
|
|
@@ -834,8 +1190,20 @@ function pluginRecord(pluginId, name, source, packageRoot, directory, folder, ve
|
|
|
834
1190
|
return { pluginId, name, version, sides: [], directory, folder, packageRoot, source };
|
|
835
1191
|
}
|
|
836
1192
|
function readPackageEntry(packageRoot, name) {
|
|
837
|
-
|
|
838
|
-
|
|
1193
|
+
// Read package boundaries directly: Node caches require.resolve() paths even
|
|
1194
|
+
// after npm moves an installation between nested and hoisted node_modules.
|
|
1195
|
+
let manifestPath;
|
|
1196
|
+
for (const root of [packageRoot, currentProjectRoot(packageRoot)]) {
|
|
1197
|
+
const localRequire = (0, module_1.createRequire)(path_1.default.join(root, "package.json"));
|
|
1198
|
+
manifestPath = (localRequire.resolve.paths(name) || [])
|
|
1199
|
+
.map((directory) => path_1.default.join(directory, name, "package.json"))
|
|
1200
|
+
.find((filename) => fs_extra_1.default.existsSync(filename));
|
|
1201
|
+
if (manifestPath)
|
|
1202
|
+
break;
|
|
1203
|
+
}
|
|
1204
|
+
if (!manifestPath)
|
|
1205
|
+
throw new Error(`Missing npm plugin package: ${name}.`);
|
|
1206
|
+
manifestPath = fs_extra_1.default.realpathSync(manifestPath);
|
|
839
1207
|
const metadata = readJson(manifestPath);
|
|
840
1208
|
if (!metadata)
|
|
841
1209
|
throw new Error(`Missing package metadata for ${name}.`);
|
|
@@ -849,7 +1217,10 @@ function sideDirectory(packageRoot, metadata, side) {
|
|
|
849
1217
|
return undefined;
|
|
850
1218
|
const target = path_1.default.resolve(packageRoot, directory);
|
|
851
1219
|
const relative = path_1.default.relative(packageRoot, target);
|
|
852
|
-
if (relative === "" ||
|
|
1220
|
+
if (relative === "" ||
|
|
1221
|
+
relative === ".." ||
|
|
1222
|
+
relative.startsWith(`..${path_1.default.sep}`) ||
|
|
1223
|
+
path_1.default.isAbsolute(relative))
|
|
853
1224
|
return undefined;
|
|
854
1225
|
return target;
|
|
855
1226
|
}
|
|
@@ -866,7 +1237,7 @@ function recordFromPackage(pluginId, name, source, packageRoot, metadata, side)
|
|
|
866
1237
|
return undefined;
|
|
867
1238
|
const directory = sideDirectory(packageRoot, metadata, target);
|
|
868
1239
|
const folder = stringValue(objectValue(elements[target])?.folder);
|
|
869
|
-
if (!directory || !folder)
|
|
1240
|
+
if (!directory || !PLUGIN_ID.test(folder))
|
|
870
1241
|
return undefined;
|
|
871
1242
|
return {
|
|
872
1243
|
...pluginRecord(pluginId, name, source, packageRoot, directory, folder, version),
|
|
@@ -886,9 +1257,24 @@ function listNpmPlugins(side, options = {}) {
|
|
|
886
1257
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
887
1258
|
if (!host)
|
|
888
1259
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
889
|
-
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
1260
|
+
const project = path_1.default.resolve(projectRoot) === path_1.default.resolve(packageRoot)
|
|
1261
|
+
? null
|
|
1262
|
+
: readProjectManifest(projectRoot);
|
|
890
1263
|
const hostMappings = mappingsOf(host);
|
|
891
|
-
const projectMappings = mappingsOf(project);
|
|
1264
|
+
const projectMappings = { ...mappingsOf(project) };
|
|
1265
|
+
for (const name of Object.keys(dependenciesOf(project))) {
|
|
1266
|
+
if (!PACKAGE_NAME.test(name) || Object.values(projectMappings).includes(name))
|
|
1267
|
+
continue;
|
|
1268
|
+
try {
|
|
1269
|
+
const entry = readPackageEntry(projectRoot, name);
|
|
1270
|
+
const id = stringValue(objectValue(entry.metadata.elementspanel)?.id);
|
|
1271
|
+
if (PLUGIN_ID.test(id) && projectMappings[id] === undefined)
|
|
1272
|
+
projectMappings[id] = name;
|
|
1273
|
+
}
|
|
1274
|
+
catch {
|
|
1275
|
+
/* npm may still be writing the package. */
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
892
1278
|
const mappings = new Map();
|
|
893
1279
|
for (const [pluginId, name] of Object.entries(projectMappings)) {
|
|
894
1280
|
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
@@ -898,6 +1284,8 @@ function listNpmPlugins(side, options = {}) {
|
|
|
898
1284
|
for (const [pluginId, name] of Object.entries(hostMappings)) {
|
|
899
1285
|
if (!PLUGIN_ID.test(pluginId) || typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
900
1286
|
continue;
|
|
1287
|
+
if (dependenciesOf(host)[name] === undefined)
|
|
1288
|
+
continue;
|
|
901
1289
|
mappings.set(pluginId, { name, source: "bundled" });
|
|
902
1290
|
}
|
|
903
1291
|
const hostDependencies = dependenciesOf(host);
|
|
@@ -913,7 +1301,7 @@ function listNpmPlugins(side, options = {}) {
|
|
|
913
1301
|
}
|
|
914
1302
|
let entry;
|
|
915
1303
|
try {
|
|
916
|
-
entry = readPackageEntry(packageRoot, mapping.name);
|
|
1304
|
+
entry = readPackageEntry(mapping.source === "project" ? projectRoot : packageRoot, mapping.name);
|
|
917
1305
|
}
|
|
918
1306
|
catch (error) {
|
|
919
1307
|
if (options.skipInvalid)
|
|
@@ -945,7 +1333,12 @@ function runNpm(args, cwd) {
|
|
|
945
1333
|
: process.platform === "win32"
|
|
946
1334
|
? {
|
|
947
1335
|
command: process.env.ComSpec || "cmd.exe",
|
|
948
|
-
args: [
|
|
1336
|
+
args: [
|
|
1337
|
+
"/d",
|
|
1338
|
+
"/s",
|
|
1339
|
+
"/c",
|
|
1340
|
+
`npm ${args.map((item) => `"${item.replace(/"/g, '""')}"`).join(" ")}`
|
|
1341
|
+
],
|
|
949
1342
|
shell: false
|
|
950
1343
|
}
|
|
951
1344
|
: { command: "npm", args, shell: false };
|
|
@@ -964,9 +1357,10 @@ function runNpm(args, cwd) {
|
|
|
964
1357
|
};
|
|
965
1358
|
child.stdout?.on("data", append);
|
|
966
1359
|
child.stderr?.on("data", append);
|
|
1360
|
+
const action = args.find((argument) => argument === "install" || argument === "uninstall") || "operation";
|
|
967
1361
|
const timer = setTimeout(() => {
|
|
968
1362
|
child.kill("SIGKILL");
|
|
969
|
-
reject(new Error(`npm ${
|
|
1363
|
+
reject(new Error(`npm ${action} timed out.`));
|
|
970
1364
|
}, 10 * 60 * 1000);
|
|
971
1365
|
timer.unref?.();
|
|
972
1366
|
child.once("error", (error) => {
|
|
@@ -977,15 +1371,69 @@ function runNpm(args, cwd) {
|
|
|
977
1371
|
clearTimeout(timer);
|
|
978
1372
|
if (code === 0)
|
|
979
1373
|
return resolve(output);
|
|
980
|
-
reject(new Error(`npm ${
|
|
1374
|
+
reject(new Error(`npm ${action} failed (${code}): ${output.trim()}`));
|
|
981
1375
|
});
|
|
982
1376
|
});
|
|
983
1377
|
}
|
|
984
|
-
const
|
|
1378
|
+
const operationsKey = Symbol.for("elementspanel.npm.operations");
|
|
1379
|
+
const shared = globalThis;
|
|
1380
|
+
const operations = (shared[operationsKey] ??= new Map());
|
|
1381
|
+
const LOCK_NAME = ".elementspanel-npm.lock";
|
|
1382
|
+
async function acquireProjectLock(projectRoot) {
|
|
1383
|
+
await fs_extra_1.default.ensureDir(projectRoot);
|
|
1384
|
+
const directory = path_1.default.join(projectRoot, LOCK_NAME);
|
|
1385
|
+
const deadline = Date.now() + 11 * 60 * 1000;
|
|
1386
|
+
while (true) {
|
|
1387
|
+
try {
|
|
1388
|
+
await fs_extra_1.default.mkdir(directory);
|
|
1389
|
+
await fs_extra_1.default.writeJson(path_1.default.join(directory, "owner.json"), { pid: process.pid });
|
|
1390
|
+
return () => fs_extra_1.default.remove(directory);
|
|
1391
|
+
}
|
|
1392
|
+
catch (error) {
|
|
1393
|
+
if (error.code !== "EEXIST")
|
|
1394
|
+
throw error;
|
|
1395
|
+
try {
|
|
1396
|
+
const owner = await fs_extra_1.default.readJson(path_1.default.join(directory, "owner.json"));
|
|
1397
|
+
try {
|
|
1398
|
+
process.kill(owner.pid, 0);
|
|
1399
|
+
}
|
|
1400
|
+
catch (failure) {
|
|
1401
|
+
if (failure.code === "ESRCH") {
|
|
1402
|
+
await fs_extra_1.default.remove(directory);
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
catch {
|
|
1408
|
+
if (Date.now() - ((await fs_extra_1.default.stat(directory).catch(() => null))?.mtimeMs ?? Date.now()) >
|
|
1409
|
+
60_000) {
|
|
1410
|
+
await fs_extra_1.default.remove(directory);
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
if (Date.now() > deadline)
|
|
1415
|
+
throw new Error("Another npm plugin operation is still running.");
|
|
1416
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
function npmPluginOperationPending() {
|
|
1421
|
+
const { packageRoot, projectRoot } = npmPluginRoots();
|
|
1422
|
+
return (operations.size > 0 ||
|
|
1423
|
+
[packageRoot, projectRoot].some((root) => fs_extra_1.default.existsSync(path_1.default.join(root, LOCK_NAME))));
|
|
1424
|
+
}
|
|
985
1425
|
function withProjectLock(projectRoot, operation) {
|
|
986
1426
|
const key = process.platform === "win32" ? projectRoot.toLowerCase() : projectRoot;
|
|
987
1427
|
const previous = operations.get(key) ?? Promise.resolve();
|
|
988
|
-
const result = previous.then(
|
|
1428
|
+
const result = previous.then(async () => {
|
|
1429
|
+
const release = await acquireProjectLock(projectRoot);
|
|
1430
|
+
try {
|
|
1431
|
+
return await operation();
|
|
1432
|
+
}
|
|
1433
|
+
finally {
|
|
1434
|
+
await release();
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
989
1437
|
const settled = result.then(() => { }, () => { });
|
|
990
1438
|
operations.set(key, settled);
|
|
991
1439
|
return result.finally(() => {
|
|
@@ -993,18 +1441,18 @@ function withProjectLock(projectRoot, operation) {
|
|
|
993
1441
|
operations.delete(key);
|
|
994
1442
|
});
|
|
995
1443
|
}
|
|
996
|
-
/**
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
*/
|
|
1444
|
+
/** Core services keep the connection and management interface available. */
|
|
1445
|
+
function isEssentialNpmPlugin(pluginId) {
|
|
1446
|
+
return ["i18n", "storage", "runtime", "server", "console", "config"].includes(pluginId);
|
|
1447
|
+
}
|
|
1448
|
+
/** npm changes dependencies and lockfiles; only append our plugin mapping afterwards. */
|
|
1002
1449
|
async function installNpmPlugin(options) {
|
|
1003
|
-
const { name,
|
|
1004
|
-
|
|
1005
|
-
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
1450
|
+
const { name, side } = options;
|
|
1451
|
+
const version = options.version || "latest";
|
|
1006
1452
|
if (!PACKAGE_NAME.test(name))
|
|
1007
1453
|
throw new Error(`Invalid npm plugin package: ${name}`);
|
|
1454
|
+
if (options.pluginId && !PLUGIN_ID.test(options.pluginId))
|
|
1455
|
+
throw new Error(`Invalid plugin id: ${options.pluginId}`);
|
|
1008
1456
|
if (!VERSION.test(version))
|
|
1009
1457
|
throw new Error(`Invalid plugin version: ${version}`);
|
|
1010
1458
|
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
@@ -1012,64 +1460,154 @@ async function installNpmPlugin(options) {
|
|
|
1012
1460
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
1013
1461
|
if (!host)
|
|
1014
1462
|
throw new Error(`Missing runtime package metadata: ${packageRoot}`);
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1463
|
+
const hostId = Object.entries(mappingsOf(host)).find(([, value]) => value === name && dependenciesOf(host)[name] !== undefined)?.[0];
|
|
1464
|
+
const targetRoot = hostId ? packageRoot : projectRoot;
|
|
1465
|
+
if (hostId && isEssentialNpmPlugin(hostId))
|
|
1466
|
+
throw new Error(`The essential plugin "${hostId}" cannot be replaced while running.`);
|
|
1467
|
+
if (options.pluginId &&
|
|
1468
|
+
mappingsOf(host)[options.pluginId] &&
|
|
1469
|
+
dependenciesOf(host)[String(mappingsOf(host)[options.pluginId])] !== undefined &&
|
|
1470
|
+
mappingsOf(host)[options.pluginId] !== name)
|
|
1471
|
+
throw new Error(`BUNDLED:${options.pluginId}`);
|
|
1472
|
+
const original = readProjectManifest(targetRoot);
|
|
1473
|
+
const previous = dependenciesOf(original)[name];
|
|
1474
|
+
let previousVersion = previous;
|
|
1475
|
+
if (previous) {
|
|
1476
|
+
try {
|
|
1477
|
+
previousVersion = readPackageEntry(targetRoot, name).metadata.version || previous;
|
|
1478
|
+
}
|
|
1479
|
+
catch {
|
|
1480
|
+
/* Keep the declared spec if the previous package is incomplete. */
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
const backups = new Map();
|
|
1484
|
+
for (const filename of ["package.json", "package-lock.json", "npm-shrinkwrap.json"]) {
|
|
1485
|
+
const target = path_1.default.join(targetRoot, filename);
|
|
1486
|
+
backups.set(target, fs_extra_1.default.existsSync(target) ? fs_extra_1.default.readFileSync(target) : null);
|
|
1487
|
+
}
|
|
1023
1488
|
try {
|
|
1024
|
-
|
|
1489
|
+
await runNpm([
|
|
1490
|
+
"--prefix",
|
|
1491
|
+
targetRoot,
|
|
1492
|
+
"install",
|
|
1493
|
+
`${name}@${version}`,
|
|
1494
|
+
"--save",
|
|
1495
|
+
"--save-exact",
|
|
1496
|
+
"--no-fund",
|
|
1497
|
+
"--no-audit",
|
|
1498
|
+
"--ignore-scripts"
|
|
1499
|
+
], targetRoot);
|
|
1500
|
+
const entry = readPackageEntry(targetRoot, name);
|
|
1501
|
+
const pluginId = options.pluginId || stringValue(objectValue(entry.metadata.elementspanel)?.id);
|
|
1502
|
+
if (!PLUGIN_ID.test(pluginId))
|
|
1503
|
+
throw new Error(`Invalid plugin id in ${name}.`);
|
|
1504
|
+
if (mappingsOf(host)[pluginId] &&
|
|
1505
|
+
dependenciesOf(host)[String(mappingsOf(host)[pluginId])] !== undefined &&
|
|
1506
|
+
mappingsOf(host)[pluginId] !== name)
|
|
1507
|
+
throw new Error(`Plugin id ${pluginId} belongs to a bundled dependency.`);
|
|
1508
|
+
if (hostId && pluginId !== hostId)
|
|
1509
|
+
throw new Error(`The package ${name} changed its plugin id from ${hostId} to ${pluginId}.`);
|
|
1510
|
+
const mapped = mappingsOf(readProjectManifest(targetRoot))[pluginId];
|
|
1511
|
+
if (mapped !== undefined && mapped !== name)
|
|
1512
|
+
throw new Error(`Plugin id ${pluginId} is already installed as ${String(mapped)}.`);
|
|
1513
|
+
const record = recordFromPackage(pluginId, name, hostId ? "bundled" : "project", entry.root, entry.metadata, side);
|
|
1514
|
+
if (!record)
|
|
1515
|
+
throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
|
|
1516
|
+
if (/^[0-9]/.test(version) && record.version !== version)
|
|
1517
|
+
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
1518
|
+
if (!process.env.EPANEL_PACKAGE_ROOT &&
|
|
1519
|
+
(0, plugin_manifest_1.discoverPlugins)(path_1.default.join(packageRoot, "plugins"), {
|
|
1520
|
+
entryFields: [],
|
|
1521
|
+
includeDisabled: true
|
|
1522
|
+
}).some((plugin) => plugin.manifest.id === pluginId))
|
|
1523
|
+
throw new Error(`Source plugin ${pluginId} cannot be replaced with an npm dependency.`);
|
|
1524
|
+
const manifest = (0, plugin_manifest_1.readPluginManifest)(record.directory);
|
|
1525
|
+
if (!manifest || manifest.id !== pluginId || manifest.version !== record.version)
|
|
1526
|
+
throw new Error(`The plugin manifest in ${name} does not match its package.`);
|
|
1527
|
+
(0, plugin_contract_1.validatePluginCompatibility)(manifest.elements);
|
|
1528
|
+
for (const field of ["backend", "frontend", "panel", "daemon", "main", "entry", "ui"]) {
|
|
1529
|
+
if (typeof manifest[field] === "string" &&
|
|
1530
|
+
!(0, plugin_manifest_1.resolvePluginEntry)(record.directory, manifest, { entryFields: [field] }))
|
|
1531
|
+
throw new Error(`Invalid ${field} entry in ${name}.`);
|
|
1532
|
+
}
|
|
1533
|
+
const others = listNpmPlugins(side, { packageRoot, projectRoot, skipInvalid: true });
|
|
1534
|
+
if (others.some((plugin) => plugin.pluginId === pluginId && plugin.name !== name))
|
|
1535
|
+
throw new Error(`Plugin id ${pluginId} is already provided by another dependency.`);
|
|
1536
|
+
const collision = others.find((plugin) => plugin.pluginId !== pluginId && plugin.folder === record.folder);
|
|
1537
|
+
if (collision)
|
|
1538
|
+
throw new Error(`Plugin asset directory ${record.folder} is already used by ${collision.name}.`);
|
|
1539
|
+
const updated = readProjectManifest(targetRoot);
|
|
1540
|
+
updated.dependencies = { ...dependenciesOf(updated), [name]: record.version };
|
|
1541
|
+
updated.elementspanel = {
|
|
1542
|
+
...objectValue(updated.elementspanel),
|
|
1543
|
+
plugins: { ...mappingsOf(updated), [pluginId]: name }
|
|
1544
|
+
};
|
|
1545
|
+
writeProjectManifest(targetRoot, updated);
|
|
1546
|
+
return record;
|
|
1025
1547
|
}
|
|
1026
1548
|
catch (error) {
|
|
1027
|
-
|
|
1549
|
+
try {
|
|
1550
|
+
await runNpm(previous
|
|
1551
|
+
? [
|
|
1552
|
+
"--prefix",
|
|
1553
|
+
targetRoot,
|
|
1554
|
+
"install",
|
|
1555
|
+
`${name}@${String(previousVersion)}`,
|
|
1556
|
+
"--save",
|
|
1557
|
+
"--no-fund",
|
|
1558
|
+
"--no-audit",
|
|
1559
|
+
"--ignore-scripts"
|
|
1560
|
+
]
|
|
1561
|
+
: [
|
|
1562
|
+
"--prefix",
|
|
1563
|
+
targetRoot,
|
|
1564
|
+
"uninstall",
|
|
1565
|
+
name,
|
|
1566
|
+
"--no-fund",
|
|
1567
|
+
"--no-audit",
|
|
1568
|
+
"--ignore-scripts"
|
|
1569
|
+
], targetRoot);
|
|
1570
|
+
}
|
|
1571
|
+
catch (rollback) {
|
|
1572
|
+
throw new Error(`${String(error)}; npm rollback failed: ${String(rollback)}`);
|
|
1573
|
+
}
|
|
1574
|
+
finally {
|
|
1575
|
+
for (const [filename, content] of backups) {
|
|
1576
|
+
if (content === null)
|
|
1577
|
+
await fs_extra_1.default.remove(filename);
|
|
1578
|
+
else
|
|
1579
|
+
await fs_extra_1.default.writeFile(filename, content);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1028
1582
|
throw error;
|
|
1029
1583
|
}
|
|
1030
|
-
const record = recordFromPackage(pluginId, name, "project", entry.root, entry.metadata, side);
|
|
1031
|
-
if (!record) {
|
|
1032
|
-
await runNpm(["uninstall", name, "--no-fund", "--no-audit", "--ignore-scripts"], projectRoot).catch(() => { });
|
|
1033
|
-
throw new Error(`The package ${name} does not provide a ${side} plugin named ${pluginId}.`);
|
|
1034
|
-
}
|
|
1035
|
-
if (record.version !== version) {
|
|
1036
|
-
await runNpm(["uninstall", name, "--no-fund", "--no-audit", "--ignore-scripts"], projectRoot).catch(() => { });
|
|
1037
|
-
throw new Error(`The installed package ${name} is ${record.version}, expected ${version}.`);
|
|
1038
|
-
}
|
|
1039
|
-
const manifest = readProjectManifest(projectRoot);
|
|
1040
|
-
const dependencies = { ...dependenciesOf(manifest), [name]: version };
|
|
1041
|
-
const elementspanel = { ...(objectValue(manifest.elementspanel) ?? {}) };
|
|
1042
|
-
const plugins = { ...mappingsOf(manifest), [pluginId]: name };
|
|
1043
|
-
manifest.dependencies = dependencies;
|
|
1044
|
-
manifest.elementspanel = { ...elementspanel, plugins };
|
|
1045
|
-
writeProjectManifest(projectRoot, manifest);
|
|
1046
|
-
return record;
|
|
1047
1584
|
});
|
|
1048
1585
|
}
|
|
1049
|
-
/**
|
|
1586
|
+
/** Remove the dependency from the manifest that owns it, preserving user configuration. */
|
|
1050
1587
|
async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
1051
1588
|
if (!PLUGIN_ID.test(pluginId))
|
|
1052
1589
|
throw new Error(`Invalid plugin id: ${pluginId}`);
|
|
1590
|
+
if (isEssentialNpmPlugin(pluginId))
|
|
1591
|
+
throw new Error(`The essential plugin "${pluginId}" cannot be uninstalled.`);
|
|
1053
1592
|
const { packageRoot, projectRoot } = npmPluginRoots(options);
|
|
1054
1593
|
return withProjectLock(projectRoot, async () => {
|
|
1055
1594
|
const host = readJson(path_1.default.join(packageRoot, "package.json"));
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1595
|
+
const bundledName = mappingsOf(host)[pluginId];
|
|
1596
|
+
const targetRoot = typeof bundledName === "string" && dependenciesOf(host)[bundledName] !== undefined
|
|
1597
|
+
? packageRoot
|
|
1598
|
+
: projectRoot;
|
|
1599
|
+
const manifest = readProjectManifest(targetRoot);
|
|
1600
|
+
const name = mappingsOf(manifest)[pluginId] ??
|
|
1601
|
+
listNpmPlugins(undefined, { packageRoot, projectRoot, skipInvalid: true }).find((item) => item.pluginId === pluginId)?.name;
|
|
1060
1602
|
if (typeof name !== "string" || !PACKAGE_NAME.test(name))
|
|
1061
1603
|
return null;
|
|
1062
1604
|
const record = listNpmPlugins(undefined, { packageRoot, projectRoot, skipInvalid: true }).find((item) => item.pluginId === pluginId);
|
|
1063
|
-
await runNpm(["uninstall", name, "--no-fund", "--no-audit", "--ignore-scripts"],
|
|
1064
|
-
const
|
|
1605
|
+
await runNpm(["--prefix", targetRoot, "uninstall", name, "--no-fund", "--no-audit", "--ignore-scripts"], targetRoot);
|
|
1606
|
+
const updated = readProjectManifest(targetRoot);
|
|
1607
|
+
const plugins = { ...mappingsOf(updated) };
|
|
1065
1608
|
delete plugins[pluginId];
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
elementspanel.plugins = plugins;
|
|
1069
|
-
else
|
|
1070
|
-
delete elementspanel.plugins;
|
|
1071
|
-
manifest.elementspanel = elementspanel;
|
|
1072
|
-
writeProjectManifest(projectRoot, manifest);
|
|
1609
|
+
updated.elementspanel = { ...objectValue(updated.elementspanel), plugins };
|
|
1610
|
+
writeProjectManifest(targetRoot, updated);
|
|
1073
1611
|
return record ?? null;
|
|
1074
1612
|
});
|
|
1075
1613
|
}
|
|
@@ -1080,6 +1618,7 @@ async function uninstallNpmPlugin(pluginId, options = {}) {
|
|
|
1080
1618
|
/***/ "../common/src/plugin_overrides.ts"
|
|
1081
1619
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1082
1620
|
|
|
1621
|
+
"use strict";
|
|
1083
1622
|
|
|
1084
1623
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1085
1624
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1168,6 +1707,7 @@ function writePluginOverride(id, patch, filename = pluginOverridesPath()) {
|
|
|
1168
1707
|
/***/ "../common/src/plugin_revision.ts"
|
|
1169
1708
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1170
1709
|
|
|
1710
|
+
"use strict";
|
|
1171
1711
|
|
|
1172
1712
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1173
1713
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1218,11 +1758,89 @@ function pluginDirectoryRevision(directory) {
|
|
|
1218
1758
|
}
|
|
1219
1759
|
|
|
1220
1760
|
|
|
1761
|
+
/***/ },
|
|
1762
|
+
|
|
1763
|
+
/***/ "../common/src/plugin_watch.ts"
|
|
1764
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1765
|
+
|
|
1766
|
+
"use strict";
|
|
1767
|
+
|
|
1768
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1769
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
1770
|
+
};
|
|
1771
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1772
|
+
exports.watchNpmPlugins = watchNpmPlugins;
|
|
1773
|
+
const node_fs_1 = __importDefault(__webpack_require__("node:fs"));
|
|
1774
|
+
const node_path_1 = __importDefault(__webpack_require__("node:path"));
|
|
1775
|
+
const plugin_npm_1 = __webpack_require__("../common/src/plugin_npm.ts");
|
|
1776
|
+
/** Poll package boundaries, allowing npm to finish replacing files before reconciliation. */
|
|
1777
|
+
function watchNpmPlugins(ctx, side, reload, changed) {
|
|
1778
|
+
const stamp = () => {
|
|
1779
|
+
const { packageRoot, projectRoot } = (0, plugin_npm_1.npmPluginRoots)();
|
|
1780
|
+
if (!node_fs_1.default.existsSync(node_path_1.default.join(packageRoot, "package.json")))
|
|
1781
|
+
return "";
|
|
1782
|
+
const files = [];
|
|
1783
|
+
for (const root of [packageRoot, projectRoot])
|
|
1784
|
+
for (const name of [
|
|
1785
|
+
"package.json",
|
|
1786
|
+
"package-lock.json",
|
|
1787
|
+
"npm-shrinkwrap.json",
|
|
1788
|
+
"node_modules/.package-lock.json"
|
|
1789
|
+
])
|
|
1790
|
+
files.push(node_path_1.default.join(root, name));
|
|
1791
|
+
for (const plugin of (0, plugin_npm_1.listNpmPlugins)(side, { skipInvalid: true }))
|
|
1792
|
+
files.push(node_path_1.default.join(plugin.packageRoot, "package.json"), node_path_1.default.join(plugin.directory, "plugin.json"));
|
|
1793
|
+
return JSON.stringify(files.map((filename) => {
|
|
1794
|
+
try {
|
|
1795
|
+
const stat = node_fs_1.default.statSync(filename);
|
|
1796
|
+
return [filename, stat.size, stat.mtimeMs, stat.ctimeMs];
|
|
1797
|
+
}
|
|
1798
|
+
catch {
|
|
1799
|
+
return [filename, null];
|
|
1800
|
+
}
|
|
1801
|
+
}));
|
|
1802
|
+
};
|
|
1803
|
+
let applied = stamp();
|
|
1804
|
+
let candidate = applied;
|
|
1805
|
+
let busy = false;
|
|
1806
|
+
ctx.setInterval(() => {
|
|
1807
|
+
if (busy || (0, plugin_npm_1.npmPluginOperationPending)())
|
|
1808
|
+
return;
|
|
1809
|
+
try {
|
|
1810
|
+
const next = stamp();
|
|
1811
|
+
if (next === applied) {
|
|
1812
|
+
candidate = next;
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
if (next !== candidate) {
|
|
1816
|
+
candidate = next;
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
busy = true;
|
|
1820
|
+
void reload()
|
|
1821
|
+
.then(() => {
|
|
1822
|
+
applied = next;
|
|
1823
|
+
candidate = next;
|
|
1824
|
+
changed?.();
|
|
1825
|
+
})
|
|
1826
|
+
.catch((error) => ctx.logger.warn("Failed to synchronize npm plugins", error))
|
|
1827
|
+
.finally(() => {
|
|
1828
|
+
busy = false;
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
catch (error) {
|
|
1832
|
+
ctx.logger.warn("Failed to inspect npm plugins", error);
|
|
1833
|
+
}
|
|
1834
|
+
}, 2000);
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
|
|
1221
1838
|
/***/ },
|
|
1222
1839
|
|
|
1223
1840
|
/***/ "../common/src/process_tools.ts"
|
|
1224
1841
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1225
1842
|
|
|
1843
|
+
"use strict";
|
|
1226
1844
|
|
|
1227
1845
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1228
1846
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1387,6 +2005,7 @@ function killProcess(pid, process, signal) {
|
|
|
1387
2005
|
/***/ "../common/src/query_wrapper.ts"
|
|
1388
2006
|
(__unused_webpack_module, exports) {
|
|
1389
2007
|
|
|
2008
|
+
"use strict";
|
|
1390
2009
|
|
|
1391
2010
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1392
2011
|
exports.QueryWrapper = exports.LocalFileSource = exports.MySqlSource = exports.QueryMapWrapper = void 0;
|
|
@@ -1500,6 +2119,7 @@ exports.QueryWrapper = QueryWrapper;
|
|
|
1500
2119
|
/***/ "../common/src/runtime_paths.ts"
|
|
1501
2120
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1502
2121
|
|
|
2122
|
+
"use strict";
|
|
1503
2123
|
|
|
1504
2124
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1505
2125
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1514,22 +2134,24 @@ exports.ensureExecutable = ensureExecutable;
|
|
|
1514
2134
|
const node_fs_1 = __importDefault(__webpack_require__("node:fs"));
|
|
1515
2135
|
const node_os_1 = __importDefault(__webpack_require__("node:os"));
|
|
1516
2136
|
const node_path_1 = __importDefault(__webpack_require__("node:path"));
|
|
2137
|
+
// @ts-ignore Shared source layout is also consumed by the Node build tools.
|
|
2138
|
+
const workspace_layout_cjs_1 = __webpack_require__("../../scripts/workspace-layout.cjs");
|
|
1517
2139
|
/** Set by the npm worker before any application module is loaded. */
|
|
1518
2140
|
function isPackagedRuntime() {
|
|
1519
2141
|
return Boolean(process.env.EPANEL_PACKAGE_ROOT);
|
|
1520
2142
|
}
|
|
1521
2143
|
/** Code and bundled assets belong to the package; cwd always belongs to the user. */
|
|
1522
2144
|
function packagePath(...parts) {
|
|
1523
|
-
return node_path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.cwd(), ...parts);
|
|
2145
|
+
return node_path_1.default.resolve(process.env.EPANEL_PACKAGE_ROOT || process.env.EPANEL_SOURCE_ROOT || process.cwd(), ...parts);
|
|
1524
2146
|
}
|
|
1525
2147
|
function npmPluginRoots(side) {
|
|
1526
2148
|
// The same resolver is used by the CLI before the bundled application starts.
|
|
1527
|
-
// A development checkout keeps it in the repository
|
|
2149
|
+
// A development checkout keeps it in the repository above core/<side>,
|
|
1528
2150
|
// so project-installed npm plugins work there as well.
|
|
1529
2151
|
const runtimeRequire = eval("require");
|
|
1530
2152
|
const resolver = isPackagedRuntime()
|
|
1531
2153
|
? packagePath("runtime/npm-plugins.cjs")
|
|
1532
|
-
: node_path_1.default.resolve(packagePath(), "
|
|
2154
|
+
: node_path_1.default.resolve(packagePath(), "../..", "scripts", "runtime", "npm-plugins.cjs");
|
|
1533
2155
|
// A development process may run from a fixture directory without a runtime
|
|
1534
2156
|
// package; there is nothing to resolve in that case.
|
|
1535
2157
|
if (!node_fs_1.default.existsSync(node_path_1.default.join(packagePath(), "package.json")))
|
|
@@ -1539,6 +2161,9 @@ function npmPluginRoots(side) {
|
|
|
1539
2161
|
const { resolveNpmPlugins } = runtimeRequire(resolver);
|
|
1540
2162
|
return resolveNpmPlugins(packagePath(), side, { skipInvalid: true }).map((record) => ({
|
|
1541
2163
|
directory: record.directory,
|
|
2164
|
+
packageRoot: record.packageRoot,
|
|
2165
|
+
packageName: record.name,
|
|
2166
|
+
npmSource: record.source,
|
|
1542
2167
|
...(record.folder ? { folder: record.folder } : {}),
|
|
1543
2168
|
// Built-in packages are part of the runtime's default configuration. A
|
|
1544
2169
|
// project dependency is installed but remains dormant until the user
|
|
@@ -1547,9 +2172,16 @@ function npmPluginRoots(side) {
|
|
|
1547
2172
|
}));
|
|
1548
2173
|
}
|
|
1549
2174
|
function packagePluginRoots(side) {
|
|
2175
|
+
const sourceCheckout = process.env.EPANEL_SOURCE_ROOT || node_path_1.default.basename(node_path_1.default.dirname(packagePath())) === "core";
|
|
1550
2176
|
const roots = isPackagedRuntime()
|
|
1551
2177
|
? []
|
|
1552
|
-
:
|
|
2178
|
+
: !sourceCheckout
|
|
2179
|
+
? [{ directory: packagePath("plugins"), defaultEnabled: true }]
|
|
2180
|
+
: (0, workspace_layout_cjs_1.sourcePlugins)(side, node_path_1.default.resolve(packagePath(), "../..")).map((plugin) => ({
|
|
2181
|
+
directory: plugin.directory,
|
|
2182
|
+
folder: plugin.folder,
|
|
2183
|
+
defaultEnabled: true
|
|
2184
|
+
}));
|
|
1553
2185
|
// Project-installed npm plugins load in development too: they are dependencies
|
|
1554
2186
|
// of the development project, not of the published runtime package.
|
|
1555
2187
|
roots.push(...npmPluginRoots(side));
|
|
@@ -1570,7 +2202,7 @@ function bundledToolPath(name) {
|
|
|
1570
2202
|
// Published daemon packages download native tools into the installation's
|
|
1571
2203
|
// writable lib directory on first start. Development checkouts use the same
|
|
1572
2204
|
// repository-local sibling of data and logs.
|
|
1573
|
-
const root =
|
|
2205
|
+
const root = node_path_1.default.resolve(process.cwd(), "lib");
|
|
1574
2206
|
const primary = node_path_1.default.join(root, filename);
|
|
1575
2207
|
// Zip-Tools names its Intel macOS binary "amd64", while Node reports "x64".
|
|
1576
2208
|
if (!node_fs_1.default.existsSync(primary) && name === "file_zip" && platform === "darwin" && arch === "x64") {
|
|
@@ -1598,6 +2230,7 @@ function ensureExecutable(filename) {
|
|
|
1598
2230
|
/***/ "../common/src/string_utils.ts"
|
|
1599
2231
|
(__unused_webpack_module, exports) {
|
|
1600
2232
|
|
|
2233
|
+
"use strict";
|
|
1601
2234
|
|
|
1602
2235
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1603
2236
|
exports.removeTrail = removeTrail;
|
|
@@ -1616,6 +2249,7 @@ function removeTrail(origin, trail) {
|
|
|
1616
2249
|
/***/ "../common/src/system_info.ts"
|
|
1617
2250
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1618
2251
|
|
|
2252
|
+
"use strict";
|
|
1619
2253
|
|
|
1620
2254
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1621
2255
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1708,6 +2342,7 @@ function systemInfo() {
|
|
|
1708
2342
|
/***/ "../common/src/system_storage.ts"
|
|
1709
2343
|
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1710
2344
|
|
|
2345
|
+
"use strict";
|
|
1711
2346
|
|
|
1712
2347
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1713
2348
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -1839,6 +2474,7 @@ exports["default"] = StorageSubsystem;
|
|
|
1839
2474
|
/***/ "../common/src/typecheck.ts"
|
|
1840
2475
|
(__unused_webpack_module, exports) {
|
|
1841
2476
|
|
|
2477
|
+
"use strict";
|
|
1842
2478
|
|
|
1843
2479
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1844
2480
|
exports.configureEntityParams = configureEntityParams;
|
|
@@ -1913,113 +2549,12 @@ function supposeValue(v, def) {
|
|
|
1913
2549
|
}
|
|
1914
2550
|
|
|
1915
2551
|
|
|
1916
|
-
/***/ },
|
|
1917
|
-
|
|
1918
|
-
/***/ "./plugins/config/src/backend/settings.ts"
|
|
1919
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1923
|
-
exports.SettingsFormService = void 0;
|
|
1924
|
-
const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
|
|
1925
|
-
const cordis_1 = __webpack_require__("cordis");
|
|
1926
|
-
const cosmokit_1 = __webpack_require__("cosmokit");
|
|
1927
|
-
/** Configuration declarations are owned by the daemon config plugin. */
|
|
1928
|
-
class SettingsFormService extends cordis_1.Service {
|
|
1929
|
-
declarations = [];
|
|
1930
|
-
constructor(ctx) {
|
|
1931
|
-
super(ctx, "settingsForm", true);
|
|
1932
|
-
}
|
|
1933
|
-
declare(declaration) {
|
|
1934
|
-
const entry = { id: this.ctx.name, declaration };
|
|
1935
|
-
return this.ctx.effect(() => {
|
|
1936
|
-
this.declarations.push(entry);
|
|
1937
|
-
return () => (0, cosmokit_1.remove)(this.declarations, entry);
|
|
1938
|
-
});
|
|
1939
|
-
}
|
|
1940
|
-
declared() {
|
|
1941
|
-
return this.declarations.map((entry) => entry.id);
|
|
1942
|
-
}
|
|
1943
|
-
async read(id) {
|
|
1944
|
-
const entry = this.declarations.find((item) => item.id === id);
|
|
1945
|
-
if (!entry) {
|
|
1946
|
-
const schema = this.ctx.plugins.configuration(id);
|
|
1947
|
-
return schema.fields.length ? schema : null;
|
|
1948
|
-
}
|
|
1949
|
-
return { id, fields: entry.declaration.fields(), values: await entry.declaration.read() };
|
|
1950
|
-
}
|
|
1951
|
-
async write(id, values) {
|
|
1952
|
-
const entry = this.declarations.find((item) => item.id === id);
|
|
1953
|
-
if (!entry)
|
|
1954
|
-
return (await this.ctx.plugins.configure(id, values)).result;
|
|
1955
|
-
return this.ctx.plugins.runExclusive(async () => {
|
|
1956
|
-
(0, mcsmanager_common_1.validatePluginSettings)(entry.declaration.fields(), values);
|
|
1957
|
-
await entry.declaration.write(values);
|
|
1958
|
-
return {
|
|
1959
|
-
saved: true,
|
|
1960
|
-
application: entry.declaration.restartRequired ? "restart-required" : "applied"
|
|
1961
|
-
};
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
exports.SettingsFormService = SettingsFormService;
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
/***/ },
|
|
1969
|
-
|
|
1970
|
-
/***/ "./plugins/config/src/i18n/index.ts"
|
|
1971
|
-
(__unused_webpack_module, exports, __webpack_require__) {
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1975
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
1976
|
-
};
|
|
1977
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1978
|
-
exports.localeMessages = void 0;
|
|
1979
|
-
const de_DE_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/de_DE.json"));
|
|
1980
|
-
const en_US_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/en_US.json"));
|
|
1981
|
-
const es_ES_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/es_ES.json"));
|
|
1982
|
-
const fr_FR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/fr_FR.json"));
|
|
1983
|
-
const ja_JP_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ja_JP.json"));
|
|
1984
|
-
const ko_KR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ko_KR.json"));
|
|
1985
|
-
const pt_BR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/pt_BR.json"));
|
|
1986
|
-
const ru_RU_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/ru_RU.json"));
|
|
1987
|
-
const th_TH_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/th_TH.json"));
|
|
1988
|
-
const tr_TR_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/tr_TR.json"));
|
|
1989
|
-
const zh_CN_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/zh_CN.json"));
|
|
1990
|
-
const zh_TW_json_1 = __importDefault(__webpack_require__("./plugins/config/src/i18n/zh_TW.json"));
|
|
1991
|
-
// The refusals this plugin's protocol handlers throw. The panel surfaces them
|
|
1992
|
-
// verbatim on its plugin manager page, so they are translated here rather than
|
|
1993
|
-
// in the panel: this daemon knows which of its own plugins may not be switched
|
|
1994
|
-
// off remotely, and it answers in the language it was told to speak.
|
|
1995
|
-
exports.localeMessages = {
|
|
1996
|
-
de_de: de_DE_json_1.default,
|
|
1997
|
-
en_us: en_US_json_1.default,
|
|
1998
|
-
es_es: es_ES_json_1.default,
|
|
1999
|
-
fr_fr: fr_FR_json_1.default,
|
|
2000
|
-
ja_jp: ja_JP_json_1.default,
|
|
2001
|
-
ko_kr: ko_KR_json_1.default,
|
|
2002
|
-
pt_br: pt_BR_json_1.default,
|
|
2003
|
-
ru_ru: ru_RU_json_1.default,
|
|
2004
|
-
th_th: th_TH_json_1.default,
|
|
2005
|
-
tr_tr: tr_TR_json_1.default,
|
|
2006
|
-
zh_cn: zh_CN_json_1.default,
|
|
2007
|
-
zh_tw: zh_TW_json_1.default
|
|
2008
|
-
};
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
/***/ },
|
|
2012
|
-
|
|
2013
|
-
/***/ "events"
|
|
2014
|
-
(module) {
|
|
2015
|
-
|
|
2016
|
-
module.exports = require("events");
|
|
2017
|
-
|
|
2018
2552
|
/***/ },
|
|
2019
2553
|
|
|
2020
2554
|
/***/ "fs-extra"
|
|
2021
2555
|
(module) {
|
|
2022
2556
|
|
|
2557
|
+
"use strict";
|
|
2023
2558
|
module.exports = require("fs-extra");
|
|
2024
2559
|
|
|
2025
2560
|
/***/ },
|
|
@@ -2027,6 +2562,7 @@ module.exports = require("fs-extra");
|
|
|
2027
2562
|
/***/ "iconv-lite"
|
|
2028
2563
|
(module) {
|
|
2029
2564
|
|
|
2565
|
+
"use strict";
|
|
2030
2566
|
module.exports = require("iconv-lite");
|
|
2031
2567
|
|
|
2032
2568
|
/***/ },
|
|
@@ -2034,6 +2570,7 @@ module.exports = require("iconv-lite");
|
|
|
2034
2570
|
/***/ "os-utils"
|
|
2035
2571
|
(module) {
|
|
2036
2572
|
|
|
2573
|
+
"use strict";
|
|
2037
2574
|
module.exports = require("os-utils");
|
|
2038
2575
|
|
|
2039
2576
|
/***/ },
|
|
@@ -2041,6 +2578,7 @@ module.exports = require("os-utils");
|
|
|
2041
2578
|
/***/ "cordis"
|
|
2042
2579
|
(module) {
|
|
2043
2580
|
|
|
2581
|
+
"use strict";
|
|
2044
2582
|
module.exports = require("cordis");
|
|
2045
2583
|
|
|
2046
2584
|
/***/ },
|
|
@@ -2048,6 +2586,7 @@ module.exports = require("cordis");
|
|
|
2048
2586
|
/***/ "cosmokit"
|
|
2049
2587
|
(module) {
|
|
2050
2588
|
|
|
2589
|
+
"use strict";
|
|
2051
2590
|
module.exports = require("cosmokit");
|
|
2052
2591
|
|
|
2053
2592
|
/***/ },
|
|
@@ -2055,6 +2594,7 @@ module.exports = require("cosmokit");
|
|
|
2055
2594
|
/***/ "child_process"
|
|
2056
2595
|
(module) {
|
|
2057
2596
|
|
|
2597
|
+
"use strict";
|
|
2058
2598
|
module.exports = require("child_process");
|
|
2059
2599
|
|
|
2060
2600
|
/***/ },
|
|
@@ -2062,13 +2602,23 @@ module.exports = require("child_process");
|
|
|
2062
2602
|
/***/ "crypto"
|
|
2063
2603
|
(module) {
|
|
2064
2604
|
|
|
2605
|
+
"use strict";
|
|
2065
2606
|
module.exports = require("crypto");
|
|
2066
2607
|
|
|
2067
2608
|
/***/ },
|
|
2068
2609
|
|
|
2610
|
+
/***/ "events"
|
|
2611
|
+
(module) {
|
|
2612
|
+
|
|
2613
|
+
"use strict";
|
|
2614
|
+
module.exports = require("events");
|
|
2615
|
+
|
|
2616
|
+
/***/ },
|
|
2617
|
+
|
|
2069
2618
|
/***/ "fs"
|
|
2070
2619
|
(module) {
|
|
2071
2620
|
|
|
2621
|
+
"use strict";
|
|
2072
2622
|
module.exports = require("fs");
|
|
2073
2623
|
|
|
2074
2624
|
/***/ },
|
|
@@ -2076,6 +2626,7 @@ module.exports = require("fs");
|
|
|
2076
2626
|
/***/ "module"
|
|
2077
2627
|
(module) {
|
|
2078
2628
|
|
|
2629
|
+
"use strict";
|
|
2079
2630
|
module.exports = require("module");
|
|
2080
2631
|
|
|
2081
2632
|
/***/ },
|
|
@@ -2083,6 +2634,7 @@ module.exports = require("module");
|
|
|
2083
2634
|
/***/ "net"
|
|
2084
2635
|
(module) {
|
|
2085
2636
|
|
|
2637
|
+
"use strict";
|
|
2086
2638
|
module.exports = require("net");
|
|
2087
2639
|
|
|
2088
2640
|
/***/ },
|
|
@@ -2090,6 +2642,7 @@ module.exports = require("net");
|
|
|
2090
2642
|
/***/ "node:crypto"
|
|
2091
2643
|
(module) {
|
|
2092
2644
|
|
|
2645
|
+
"use strict";
|
|
2093
2646
|
module.exports = require("node:crypto");
|
|
2094
2647
|
|
|
2095
2648
|
/***/ },
|
|
@@ -2097,13 +2650,23 @@ module.exports = require("node:crypto");
|
|
|
2097
2650
|
/***/ "node:fs"
|
|
2098
2651
|
(module) {
|
|
2099
2652
|
|
|
2653
|
+
"use strict";
|
|
2100
2654
|
module.exports = require("node:fs");
|
|
2101
2655
|
|
|
2102
2656
|
/***/ },
|
|
2103
2657
|
|
|
2658
|
+
/***/ "node:module"
|
|
2659
|
+
(module) {
|
|
2660
|
+
|
|
2661
|
+
"use strict";
|
|
2662
|
+
module.exports = require("node:module");
|
|
2663
|
+
|
|
2664
|
+
/***/ },
|
|
2665
|
+
|
|
2104
2666
|
/***/ "node:os"
|
|
2105
2667
|
(module) {
|
|
2106
2668
|
|
|
2669
|
+
"use strict";
|
|
2107
2670
|
module.exports = require("node:os");
|
|
2108
2671
|
|
|
2109
2672
|
/***/ },
|
|
@@ -2111,13 +2674,23 @@ module.exports = require("node:os");
|
|
|
2111
2674
|
/***/ "node:path"
|
|
2112
2675
|
(module) {
|
|
2113
2676
|
|
|
2677
|
+
"use strict";
|
|
2114
2678
|
module.exports = require("node:path");
|
|
2115
2679
|
|
|
2116
2680
|
/***/ },
|
|
2117
2681
|
|
|
2682
|
+
/***/ "node:url"
|
|
2683
|
+
(module) {
|
|
2684
|
+
|
|
2685
|
+
"use strict";
|
|
2686
|
+
module.exports = require("node:url");
|
|
2687
|
+
|
|
2688
|
+
/***/ },
|
|
2689
|
+
|
|
2118
2690
|
/***/ "os"
|
|
2119
2691
|
(module) {
|
|
2120
2692
|
|
|
2693
|
+
"use strict";
|
|
2121
2694
|
module.exports = require("os");
|
|
2122
2695
|
|
|
2123
2696
|
/***/ },
|
|
@@ -2125,6 +2698,7 @@ module.exports = require("os");
|
|
|
2125
2698
|
/***/ "path"
|
|
2126
2699
|
(module) {
|
|
2127
2700
|
|
|
2701
|
+
"use strict";
|
|
2128
2702
|
module.exports = require("path");
|
|
2129
2703
|
|
|
2130
2704
|
/***/ },
|
|
@@ -2132,91 +2706,158 @@ module.exports = require("path");
|
|
|
2132
2706
|
/***/ "process"
|
|
2133
2707
|
(module) {
|
|
2134
2708
|
|
|
2709
|
+
"use strict";
|
|
2135
2710
|
module.exports = require("process");
|
|
2136
2711
|
|
|
2137
2712
|
/***/ },
|
|
2138
2713
|
|
|
2139
|
-
/***/ "
|
|
2714
|
+
/***/ "../../scripts/workspace-layout.cjs"
|
|
2715
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
2716
|
+
|
|
2717
|
+
const fs = __webpack_require__("node:fs");
|
|
2718
|
+
const path = __webpack_require__("node:path");
|
|
2719
|
+
|
|
2720
|
+
const repository = path.resolve(__dirname, "..");
|
|
2721
|
+
const coreDirectory = (side, root = repository) => path.join(root, "core", side);
|
|
2722
|
+
const developmentDirectory = (side, root = repository) => path.join(root, "data", side);
|
|
2723
|
+
|
|
2724
|
+
/** Source packages use the same per-side metadata as their published npm packages. */
|
|
2725
|
+
function sourcePlugins(side, root = repository) {
|
|
2726
|
+
if (!["panel", "daemon"].includes(side)) throw new Error(`Unknown plugin side: ${side}`);
|
|
2727
|
+
const directory = path.join(root, "plugins");
|
|
2728
|
+
if (!fs.existsSync(directory)) return [];
|
|
2729
|
+
const plugins = [];
|
|
2730
|
+
for (const item of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
2731
|
+
if (!item.isDirectory()) continue;
|
|
2732
|
+
const packageRoot = path.join(directory, item.name);
|
|
2733
|
+
const filename = path.join(packageRoot, "package.json");
|
|
2734
|
+
if (!fs.existsSync(filename)) continue;
|
|
2735
|
+
const metadata = JSON.parse(fs.readFileSync(filename, "utf8"));
|
|
2736
|
+
const definition = metadata.elementspanel?.[side];
|
|
2737
|
+
if (!definition) continue;
|
|
2738
|
+
const id = metadata.elementspanel.id;
|
|
2739
|
+
if (typeof id !== "string" || typeof definition.directory !== "string")
|
|
2740
|
+
throw new Error(`Invalid ${side} plugin metadata: ${filename}`);
|
|
2741
|
+
const pluginDirectory = path.resolve(packageRoot, definition.directory);
|
|
2742
|
+
const relative = path.relative(packageRoot, pluginDirectory);
|
|
2743
|
+
if (
|
|
2744
|
+
!relative ||
|
|
2745
|
+
relative === ".." ||
|
|
2746
|
+
relative.startsWith(`..${path.sep}`) ||
|
|
2747
|
+
path.isAbsolute(relative)
|
|
2748
|
+
)
|
|
2749
|
+
throw new Error(`Plugin directory must stay inside its package: ${filename}`);
|
|
2750
|
+
if (!fs.existsSync(path.join(pluginDirectory, "plugin.json")))
|
|
2751
|
+
throw new Error(`Missing ${side} plugin manifest: ${pluginDirectory}`);
|
|
2752
|
+
plugins.push({
|
|
2753
|
+
id,
|
|
2754
|
+
folder: definition.folder || id,
|
|
2755
|
+
directory: pluginDirectory,
|
|
2756
|
+
packageRoot,
|
|
2757
|
+
metadata
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
return plugins.sort((a, b) => a.id.localeCompare(b.id));
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
module.exports = { repository, coreDirectory, developmentDirectory, sourcePlugins };
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
/***/ },
|
|
2767
|
+
|
|
2768
|
+
/***/ "../../plugins/config/daemon/src/i18n/de_DE.json"
|
|
2140
2769
|
(module) {
|
|
2141
2770
|
|
|
2142
|
-
|
|
2771
|
+
"use strict";
|
|
2772
|
+
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."}');
|
|
2143
2773
|
|
|
2144
2774
|
/***/ },
|
|
2145
2775
|
|
|
2146
|
-
/***/ "
|
|
2776
|
+
/***/ "../../plugins/config/daemon/src/i18n/en_US.json"
|
|
2147
2777
|
(module) {
|
|
2148
2778
|
|
|
2149
|
-
|
|
2779
|
+
"use strict";
|
|
2780
|
+
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."}');
|
|
2150
2781
|
|
|
2151
2782
|
/***/ },
|
|
2152
2783
|
|
|
2153
|
-
/***/ "
|
|
2784
|
+
/***/ "../../plugins/config/daemon/src/i18n/es_ES.json"
|
|
2154
2785
|
(module) {
|
|
2155
2786
|
|
|
2156
|
-
|
|
2787
|
+
"use strict";
|
|
2788
|
+
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."}');
|
|
2157
2789
|
|
|
2158
2790
|
/***/ },
|
|
2159
2791
|
|
|
2160
|
-
/***/ "
|
|
2792
|
+
/***/ "../../plugins/config/daemon/src/i18n/fr_FR.json"
|
|
2161
2793
|
(module) {
|
|
2162
2794
|
|
|
2163
|
-
|
|
2795
|
+
"use strict";
|
|
2796
|
+
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."}');
|
|
2164
2797
|
|
|
2165
2798
|
/***/ },
|
|
2166
2799
|
|
|
2167
|
-
/***/ "
|
|
2800
|
+
/***/ "../../plugins/config/daemon/src/i18n/ja_JP.json"
|
|
2168
2801
|
(module) {
|
|
2169
2802
|
|
|
2170
|
-
|
|
2803
|
+
"use strict";
|
|
2804
|
+
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 に設定してください。"}');
|
|
2171
2805
|
|
|
2172
2806
|
/***/ },
|
|
2173
2807
|
|
|
2174
|
-
/***/ "
|
|
2808
|
+
/***/ "../../plugins/config/daemon/src/i18n/ko_KR.json"
|
|
2175
2809
|
(module) {
|
|
2176
2810
|
|
|
2177
|
-
|
|
2811
|
+
"use strict";
|
|
2812
|
+
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 로 설정하세요."}');
|
|
2178
2813
|
|
|
2179
2814
|
/***/ },
|
|
2180
2815
|
|
|
2181
|
-
/***/ "
|
|
2816
|
+
/***/ "../../plugins/config/daemon/src/i18n/pt_BR.json"
|
|
2182
2817
|
(module) {
|
|
2183
2818
|
|
|
2184
|
-
|
|
2819
|
+
"use strict";
|
|
2820
|
+
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."}');
|
|
2185
2821
|
|
|
2186
2822
|
/***/ },
|
|
2187
2823
|
|
|
2188
|
-
/***/ "
|
|
2824
|
+
/***/ "../../plugins/config/daemon/src/i18n/ru_RU.json"
|
|
2189
2825
|
(module) {
|
|
2190
2826
|
|
|
2191
|
-
|
|
2827
|
+
"use strict";
|
|
2828
|
+
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 на хосте."}');
|
|
2192
2829
|
|
|
2193
2830
|
/***/ },
|
|
2194
2831
|
|
|
2195
|
-
/***/ "
|
|
2832
|
+
/***/ "../../plugins/config/daemon/src/i18n/th_TH.json"
|
|
2196
2833
|
(module) {
|
|
2197
2834
|
|
|
2198
|
-
|
|
2835
|
+
"use strict";
|
|
2836
|
+
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 ของมันบนเครื่องโฮสต์"}');
|
|
2199
2837
|
|
|
2200
2838
|
/***/ },
|
|
2201
2839
|
|
|
2202
|
-
/***/ "
|
|
2840
|
+
/***/ "../../plugins/config/daemon/src/i18n/tr_TR.json"
|
|
2203
2841
|
(module) {
|
|
2204
2842
|
|
|
2205
|
-
|
|
2843
|
+
"use strict";
|
|
2844
|
+
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."}');
|
|
2206
2845
|
|
|
2207
2846
|
/***/ },
|
|
2208
2847
|
|
|
2209
|
-
/***/ "
|
|
2848
|
+
/***/ "../../plugins/config/daemon/src/i18n/zh_CN.json"
|
|
2210
2849
|
(module) {
|
|
2211
2850
|
|
|
2212
|
-
|
|
2851
|
+
"use strict";
|
|
2852
|
+
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。"}');
|
|
2213
2853
|
|
|
2214
2854
|
/***/ },
|
|
2215
2855
|
|
|
2216
|
-
/***/ "
|
|
2856
|
+
/***/ "../../plugins/config/daemon/src/i18n/zh_TW.json"
|
|
2217
2857
|
(module) {
|
|
2218
2858
|
|
|
2219
|
-
|
|
2859
|
+
"use strict";
|
|
2860
|
+
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。"}');
|
|
2220
2861
|
|
|
2221
2862
|
/***/ }
|
|
2222
2863
|
|
|
@@ -2248,16 +2889,18 @@ module.exports = /*#__PURE__*/JSON.parse('{"TXT_CODE_DAEMON_PLUGIN_ESSENTIAL_DIS
|
|
|
2248
2889
|
/******/
|
|
2249
2890
|
/************************************************************************/
|
|
2250
2891
|
var __webpack_exports__ = {};
|
|
2251
|
-
// This entry needs to be wrapped in an IIFE because it
|
|
2892
|
+
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
|
|
2252
2893
|
(() => {
|
|
2894
|
+
"use strict";
|
|
2253
2895
|
var exports = __webpack_exports__;
|
|
2254
2896
|
|
|
2255
2897
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2256
2898
|
exports.inject = void 0;
|
|
2257
2899
|
exports.apply = apply;
|
|
2258
2900
|
const mcsmanager_common_1 = __webpack_require__("../common/src/index.ts");
|
|
2259
|
-
const i18n_1 = __webpack_require__("
|
|
2260
|
-
const settings_1 = __webpack_require__("
|
|
2901
|
+
const i18n_1 = __webpack_require__("../../plugins/config/daemon/src/i18n/index.ts");
|
|
2902
|
+
const settings_1 = __webpack_require__("../../plugins/config/daemon/src/backend/settings.ts");
|
|
2903
|
+
const mcsmanager_common_2 = __webpack_require__("../common/src/index.ts");
|
|
2261
2904
|
// Daemon side of the plugin manager. The daemon core owns the mechanism —
|
|
2262
2905
|
// `ctx.plugins` lists what is installed and persists the enable switch — and
|
|
2263
2906
|
// this plugin only exposes it over the protocol, because the panel's plugin
|
|
@@ -2376,11 +3019,10 @@ function apply(ctx) {
|
|
|
2376
3019
|
ctx.protocol.on("plugin/npm/install", async (routerCtx, data) => {
|
|
2377
3020
|
try {
|
|
2378
3021
|
const payload = (data ?? {});
|
|
2379
|
-
const record = await
|
|
3022
|
+
const record = await ctx.plugins.install({
|
|
2380
3023
|
name: String(payload.name ?? ""),
|
|
2381
|
-
pluginId: String(payload.pluginId
|
|
2382
|
-
version: String(payload.version
|
|
2383
|
-
side: "daemon"
|
|
3024
|
+
pluginId: payload.pluginId ? String(payload.pluginId) : undefined,
|
|
3025
|
+
version: payload.version ? String(payload.version) : undefined
|
|
2384
3026
|
});
|
|
2385
3027
|
ctx.protocol.response(routerCtx, record);
|
|
2386
3028
|
}
|
|
@@ -2391,16 +3033,18 @@ function apply(ctx) {
|
|
|
2391
3033
|
ctx.protocol.on("plugin/npm/uninstall", async (routerCtx, data) => {
|
|
2392
3034
|
try {
|
|
2393
3035
|
const pluginId = String(data?.pluginId ?? "");
|
|
2394
|
-
|
|
2395
|
-
|
|
3036
|
+
await ctx.plugins.remove(pluginId);
|
|
3037
|
+
if (data?.removeConfig === true) {
|
|
3038
|
+
await ctx.plugins.runExclusive(async () => (0, mcsmanager_common_2.writePluginOverride)(pluginId, { config: {} }));
|
|
3039
|
+
}
|
|
3040
|
+
ctx.protocol.response(routerCtx, { removed: true, pluginId });
|
|
2396
3041
|
}
|
|
2397
3042
|
catch (error) {
|
|
2398
3043
|
ctx.protocol.responseError(routerCtx, error);
|
|
2399
3044
|
}
|
|
2400
3045
|
});
|
|
2401
|
-
//
|
|
2402
|
-
//
|
|
2403
|
-
// from a newly loaded plugin are bound to a fresh socket.
|
|
3046
|
+
// Reconcile dependencies and make their current handlers available on
|
|
3047
|
+
// existing authenticated sockets.
|
|
2404
3048
|
ctx.protocol.on("plugin/reload", async (routerCtx) => {
|
|
2405
3049
|
try {
|
|
2406
3050
|
await ctx.plugins.reload();
|