@nocobase/server 2.1.0-alpha.2 → 2.1.0-alpha.21

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.
Files changed (51) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/acl/available-action.js +1 -1
  4. package/lib/aes-encryptor.js +3 -2
  5. package/lib/ai/create-docs-index.js +2 -1
  6. package/lib/app-supervisor/app-options-factory.d.ts +1 -0
  7. package/lib/app-supervisor/index.js +15 -1
  8. package/lib/app-supervisor/main-only-adapter.d.ts +1 -1
  9. package/lib/app-supervisor/main-only-adapter.js +17 -12
  10. package/lib/application.d.ts +1 -2
  11. package/lib/application.js +3 -24
  12. package/lib/commands/create-migration.js +1 -1
  13. package/lib/commands/install.js +3 -1
  14. package/lib/commands/pm.js +7 -0
  15. package/lib/commands/start.js +2 -2
  16. package/lib/commands/upgrade.js +3 -1
  17. package/lib/event-queue.js +1 -1
  18. package/lib/gateway/index.d.ts +13 -3
  19. package/lib/gateway/index.js +137 -15
  20. package/lib/gateway/utils.d.ts +17 -0
  21. package/lib/gateway/utils.js +115 -0
  22. package/lib/helper.js +33 -1
  23. package/lib/index.d.ts +1 -0
  24. package/lib/index.js +2 -0
  25. package/lib/main-data-source.js +1 -1
  26. package/lib/plugin-manager/deps.js +2 -1
  27. package/lib/plugin-manager/options/resource.d.ts +11 -1
  28. package/lib/plugin-manager/options/resource.js +153 -53
  29. package/lib/plugin-manager/plugin-manager.d.ts +7 -2
  30. package/lib/plugin-manager/plugin-manager.js +56 -43
  31. package/lib/plugin-manager/utils.d.ts +7 -1
  32. package/lib/plugin-manager/utils.js +33 -9
  33. package/lib/plugin.js +47 -2
  34. package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
  35. package/lib/pub-sub-manager/handler-manager.js +11 -0
  36. package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
  37. package/lib/swagger/app.d.ts +102 -0
  38. package/lib/swagger/app.js +124 -0
  39. package/lib/swagger/base.d.ts +244 -0
  40. package/lib/swagger/base.js +292 -0
  41. package/lib/swagger/collections.d.ts +996 -0
  42. package/lib/swagger/collections.js +1264 -0
  43. package/lib/swagger/index.d.ts +1774 -0
  44. package/lib/swagger/index.js +70 -0
  45. package/lib/swagger/pm.d.ts +462 -0
  46. package/lib/swagger/pm.js +422 -0
  47. package/lib/sync-message-manager.js +8 -1
  48. package/lib/worker-mode.d.ts +19 -0
  49. package/lib/worker-mode.js +67 -0
  50. package/package.json +18 -18
  51. package/lib/swagger/index.json +0 -1569
@@ -39,45 +39,128 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
39
39
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
40
40
  var resource_exports = {};
41
41
  __export(resource_exports, {
42
+ PackageUrls: () => PackageUrls,
42
43
  default: () => resource_default
43
44
  });
44
45
  module.exports = __toCommonJS(resource_exports);
45
46
  var import_utils = require("@nocobase/utils");
47
+ var import_crypto = __toESM(require("crypto"));
46
48
  var import_fs = __toESM(require("fs"));
47
49
  var import_fs_extra = __toESM(require("fs-extra"));
48
50
  var import_path = __toESM(require("path"));
51
+ var import_utils2 = require("../utils");
52
+ var import_package = __toESM(require("../../../package.json"));
53
+ const PLUGIN_CLIENT_ENTRY_FILES = {
54
+ client: "dist/client/index.js",
55
+ "client-v2": "dist/client-v2/index.js"
56
+ };
57
+ const PLUGIN_CLIENT_MARKER_FILES = {
58
+ client: "client.js",
59
+ "client-v2": "client-v2.js"
60
+ };
49
61
  const _PackageUrls = class _PackageUrls {
50
- static async get(packageName) {
51
- if (!this.items[packageName]) {
52
- this.items[packageName] = await this.fetch(packageName);
62
+ static clear() {
63
+ this.items = {};
64
+ }
65
+ static getCacheKey(packageName, lane) {
66
+ return `${lane}:${packageName}`;
67
+ }
68
+ static async get(packageName, lane = "client") {
69
+ const cacheKey = this.getCacheKey(packageName, lane);
70
+ if (!this.items[cacheKey]) {
71
+ this.items[cacheKey] = await this.fetch(packageName, lane);
72
+ }
73
+ return this.items[cacheKey];
74
+ }
75
+ static async hasClientEntry(packageName, lane) {
76
+ const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, packageName);
77
+ if (!await import_fs_extra.default.exists(pkgPath)) {
78
+ return false;
53
79
  }
54
- return this.items[packageName];
80
+ return await import_fs_extra.default.exists(import_path.default.resolve(pkgPath, PLUGIN_CLIENT_MARKER_FILES[lane]));
55
81
  }
56
- static async fetch(packageName) {
57
- const PLUGIN_CLIENT_ENTRY_FILE = "dist/client/index.js";
82
+ static async fetch(packageName, lane = "client") {
83
+ const pluginClientEntryFile = PLUGIN_CLIENT_ENTRY_FILES[lane];
58
84
  const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, packageName);
59
- const r = await import_fs_extra.default.exists(pkgPath);
60
- if (r) {
61
- let t = "";
62
- const dist = import_path.default.resolve(pkgPath, PLUGIN_CLIENT_ENTRY_FILE);
63
- const distExists = await import_fs_extra.default.exists(dist);
64
- if (distExists) {
65
- const fsState = await import_fs_extra.default.stat(distExists ? dist : pkgPath);
66
- t = `?t=${fsState.mtime.getTime()}`;
67
- }
68
- const cdnBaseUrl = process.env.CDN_BASE_URL.replace(/\/+$/, "");
69
- const url = `${cdnBaseUrl}${"/static/plugins/"}${packageName}/${PLUGIN_CLIENT_ENTRY_FILE}${t}`;
70
- return url;
85
+ const pkgExists = await import_fs_extra.default.exists(pkgPath);
86
+ if (!pkgExists) {
87
+ return;
88
+ }
89
+ let t = "";
90
+ const dist = import_path.default.resolve(pkgPath, pluginClientEntryFile);
91
+ const distExists = await import_fs_extra.default.exists(dist);
92
+ if (distExists) {
93
+ const fsState = await import_fs_extra.default.stat(dist);
94
+ const appKey = process.env.APP_KEY || "";
95
+ let version = "";
96
+ try {
97
+ const pkgJson = await import_fs_extra.default.readJson(import_path.default.resolve(pkgPath, "package.json"));
98
+ if (pkgJson && typeof pkgJson.version === "string") {
99
+ version = pkgJson.version;
100
+ }
101
+ } catch (error) {
102
+ }
103
+ const appVersion = import_package.default.version;
104
+ const salt = process.env.PLUGIN_URL_HASH_SALT || "";
105
+ const hash = import_crypto.default.createHash("sha256").update(fsState.mtime.getTime() + appKey + version + appVersion + salt).digest("hex").slice(0, 8);
106
+ t = `?hash=${hash}`;
71
107
  }
108
+ const cdnBaseUrl = process.env.CDN_BASE_URL.replace(/\/+$/, "");
109
+ const url = `${cdnBaseUrl}${"/static/plugins/"}${packageName}/${pluginClientEntryFile}${t}`;
110
+ return url;
72
111
  }
73
112
  };
74
113
  __name(_PackageUrls, "PackageUrls");
75
114
  __publicField(_PackageUrls, "items", {});
76
115
  let PackageUrls = _PackageUrls;
116
+ async function listEnabledPlugins(ctx, lane = "client") {
117
+ const pm = ctx.db.getRepository("applicationPlugins");
118
+ const items = await pm.find({
119
+ filter: {
120
+ enabled: true
121
+ }
122
+ });
123
+ const arr = [];
124
+ for (const item of items) {
125
+ if (lane === "client-v2" && !await PackageUrls.hasClientEntry(item.packageName, lane)) {
126
+ continue;
127
+ }
128
+ const url = await PackageUrls.get(item.packageName, lane);
129
+ const { name, packageName, options } = item.toJSON();
130
+ if (url) {
131
+ arr.push({
132
+ name,
133
+ packageName,
134
+ options,
135
+ url
136
+ });
137
+ }
138
+ }
139
+ return arr;
140
+ }
141
+ __name(listEnabledPlugins, "listEnabledPlugins");
142
+ function normalizePmPluginKeys(filterByTk) {
143
+ return filterByTk.split(",").map((k) => k.trim()).filter(Boolean);
144
+ }
145
+ __name(normalizePmPluginKeys, "normalizePmPluginKeys");
146
+ function coerceAwaitResponse(value) {
147
+ if (value === true || value === 1) {
148
+ return true;
149
+ }
150
+ if (typeof value === "string") {
151
+ const v = value.trim().toLowerCase();
152
+ return v === "true" || v === "1" || v === "yes";
153
+ }
154
+ return false;
155
+ }
156
+ __name(coerceAwaitResponse, "coerceAwaitResponse");
77
157
  var resource_default = {
78
158
  name: "pm",
79
159
  actions: {
80
160
  async add(ctx, next) {
161
+ if (process.env.DISABLE_PM_ADD === "true") {
162
+ ctx.throw(403, "The current environment does not allow adding plugins online");
163
+ }
81
164
  const app = ctx.app;
82
165
  const { values = {} } = ctx.action.params;
83
166
  if (values == null ? void 0 : values.packageName) {
@@ -93,12 +176,12 @@ var resource_default = {
93
176
  }
94
177
  app.runAsCLI(["pm", "add", values.packageName, ...args], { from: "user" });
95
178
  } else if (ctx.file) {
96
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
179
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
97
180
  try {
98
181
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
99
182
  } catch (error) {
100
183
  }
101
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
184
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
102
185
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
103
186
  app.runAsCLI(["pm", "add", tempFile], { from: "user" });
104
187
  } else if (values.compressedFileUrl) {
@@ -108,6 +191,9 @@ var resource_default = {
108
191
  await next();
109
192
  },
110
193
  async update(ctx, next) {
194
+ if (process.env.DISABLE_PM_ADD === "true") {
195
+ ctx.throw(403, "The current environment does not allow adding plugins online");
196
+ }
111
197
  const app = ctx.app;
112
198
  const values = ctx.action.params.values || {};
113
199
  const args = [];
@@ -122,12 +208,12 @@ var resource_default = {
122
208
  }
123
209
  if (ctx.file) {
124
210
  values.packageName = ctx.request.body.packageName;
125
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
211
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
126
212
  try {
127
213
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
128
214
  } catch (error) {
129
215
  }
130
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
216
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
131
217
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
132
218
  values.compressedFileUrl = tempFile;
133
219
  }
@@ -145,23 +231,46 @@ var resource_default = {
145
231
  await next();
146
232
  },
147
233
  async enable(ctx, next) {
148
- const { filterByTk } = ctx.action.params;
234
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
149
235
  const app = ctx.app;
150
- if (!filterByTk) {
236
+ if (filterByTk == null || filterByTk === "" || typeof filterByTk !== "string") {
237
+ ctx.throw(400, "plugin name invalid");
238
+ }
239
+ const keys = normalizePmPluginKeys(filterByTk);
240
+ if (!keys.length) {
151
241
  ctx.throw(400, "plugin name invalid");
152
242
  }
153
- const keys = Array.isArray(filterByTk) ? filterByTk : [filterByTk];
154
- app.runAsCLI(["pm", "enable", ...keys], { from: "user" });
243
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
244
+ const argv = ["pm", "enable", ...keys];
245
+ if (awaitResponse) {
246
+ await app.runAsCLI(argv, { from: "user", throwError: true });
247
+ } else {
248
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
249
+ app.log.error(err);
250
+ });
251
+ }
155
252
  ctx.body = filterByTk;
156
253
  await next();
157
254
  },
158
255
  async disable(ctx, next) {
159
- const { filterByTk } = ctx.action.params;
160
- if (!filterByTk) {
256
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
257
+ const app = ctx.app;
258
+ if (filterByTk == null || filterByTk === "" || typeof filterByTk !== "string") {
161
259
  ctx.throw(400, "plugin name invalid");
162
260
  }
163
- const app = ctx.app;
164
- app.runAsCLI(["pm", "disable", filterByTk], { from: "user" });
261
+ const keys = normalizePmPluginKeys(filterByTk);
262
+ if (!keys.length) {
263
+ ctx.throw(400, "plugin name invalid");
264
+ }
265
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
266
+ const argv = ["pm", "disable", ...keys];
267
+ if (awaitResponse) {
268
+ await app.runAsCLI(argv, { from: "user", throwError: true });
269
+ } else {
270
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
271
+ app.log.error(err);
272
+ });
273
+ }
165
274
  ctx.body = filterByTk;
166
275
  await next();
167
276
  },
@@ -176,6 +285,11 @@ var resource_default = {
176
285
  await next();
177
286
  },
178
287
  async list(ctx, next) {
288
+ const { mode } = ctx.action.params;
289
+ if (mode === "summary") {
290
+ ctx.body = await (0, import_utils2.pmListSummary)(ctx.app);
291
+ return next();
292
+ }
179
293
  const locale = ctx.getCurrentLocale();
180
294
  const pm = ctx.app.pm;
181
295
  const plugin = pm.get("nocobase");
@@ -183,29 +297,11 @@ var resource_default = {
183
297
  await next();
184
298
  },
185
299
  async listEnabled(ctx, next) {
186
- const toArr = /* @__PURE__ */ __name(async () => {
187
- const pm = ctx.db.getRepository("applicationPlugins");
188
- const items = await pm.find({
189
- filter: {
190
- enabled: true
191
- }
192
- });
193
- const arr = [];
194
- for (const item of items) {
195
- const url = await PackageUrls.get(item.packageName);
196
- const { name, packageName, options } = item.toJSON();
197
- if (url) {
198
- arr.push({
199
- name,
200
- packageName,
201
- options,
202
- url
203
- });
204
- }
205
- }
206
- return arr;
207
- }, "toArr");
208
- ctx.body = await toArr();
300
+ ctx.body = await listEnabledPlugins(ctx, "client");
301
+ await next();
302
+ },
303
+ async listEnabledV2(ctx, next) {
304
+ ctx.body = await listEnabledPlugins(ctx, "client-v2");
209
305
  await next();
210
306
  },
211
307
  async get(ctx, next) {
@@ -221,3 +317,7 @@ var resource_default = {
221
317
  }
222
318
  }
223
319
  };
320
+ // Annotate the CommonJS export names for ESM import in node:
321
+ 0 && (module.exports = {
322
+ PackageUrls
323
+ });
@@ -13,7 +13,6 @@ import Application from '../application';
13
13
  import { Plugin } from '../plugin';
14
14
  import { PluginManagerRepository } from './plugin-manager-repository';
15
15
  import { PluginData } from './types';
16
- import { checkAndGetCompatible } from './utils';
17
16
  export declare const sleep: (timeout?: number) => Promise<unknown>;
18
17
  export interface PluginManagerOptions {
19
18
  app: Application;
@@ -29,7 +28,12 @@ export declare class AddPresetError extends Error {
29
28
  }
30
29
  export declare class PluginManager {
31
30
  options: PluginManagerOptions;
32
- static checkAndGetCompatible: typeof checkAndGetCompatible;
31
+ private static compatibleCache;
32
+ private static compatiblePending;
33
+ static checkAndGetCompatible(packageName: string): Promise<{
34
+ isCompatible: boolean;
35
+ depsCompatible: import("./utils").DepCompatible[];
36
+ }>;
33
37
  /**
34
38
  * @internal
35
39
  */
@@ -95,6 +99,7 @@ export declare class PluginManager {
95
99
  create(pluginName: string, options?: {
96
100
  forceRecreate?: boolean;
97
101
  }): Promise<void>;
102
+ addOrThrow(plugin?: string | typeof Plugin, options?: any, insert?: boolean, isUpgrade?: boolean): Promise<void>;
98
103
  add(plugin?: string | typeof Plugin, options?: any, insert?: boolean, isUpgrade?: boolean): Promise<void>;
99
104
  /**
100
105
  * @internal
@@ -58,6 +58,14 @@ var import_collection = __toESM(require("./options/collection"));
58
58
  var import_resource = __toESM(require("./options/resource"));
59
59
  var import_plugin_manager_repository = require("./plugin-manager-repository");
60
60
  var import_utils2 = require("./utils");
61
+ const _PluginLoadError = class _PluginLoadError extends Error {
62
+ constructor(pluginName) {
63
+ super(`${pluginName} plugin load error`);
64
+ this.name = "PluginLoadError";
65
+ }
66
+ };
67
+ __name(_PluginLoadError, "PluginLoadError");
68
+ let PluginLoadError = _PluginLoadError;
61
69
  const sleep = /* @__PURE__ */ __name(async (timeout = 0) => {
62
70
  return new Promise((resolve2) => {
63
71
  setTimeout(resolve2, timeout);
@@ -82,6 +90,7 @@ const _PluginManager = class _PluginManager {
82
90
  this._repository.setPluginManager(this);
83
91
  this.app.resourcer.define(import_resource.default);
84
92
  this.app.acl.allow("pm", "listEnabled", "public");
93
+ this.app.acl.allow("pm", "listEnabledV2", "public");
85
94
  this.app.acl.registerSnippet({
86
95
  name: "pm",
87
96
  actions: ["pm:*"]
@@ -92,6 +101,23 @@ const _PluginManager = class _PluginManager {
92
101
  });
93
102
  this.app.resourceManager.use(import_middleware.uploadMiddleware, { tag: "upload", after: "acl" });
94
103
  }
104
+ static async checkAndGetCompatible(packageName) {
105
+ if (this.compatibleCache.has(packageName)) {
106
+ return this.compatibleCache.get(packageName);
107
+ }
108
+ const pending = this.compatiblePending.get(packageName);
109
+ if (pending) {
110
+ return pending;
111
+ }
112
+ const task = (0, import_utils2.checkAndGetCompatible)(packageName).then((compatible) => {
113
+ this.compatibleCache.set(packageName, compatible);
114
+ return compatible;
115
+ }).finally(() => {
116
+ this.compatiblePending.delete(packageName);
117
+ });
118
+ this.compatiblePending.set(packageName, task);
119
+ return task;
120
+ }
95
121
  /**
96
122
  * @internal
97
123
  */
@@ -297,43 +323,28 @@ const _PluginManager = class _PluginManager {
297
323
  });
298
324
  await (0, import_helper.tsxRerunning)();
299
325
  }
300
- async add(plugin, options = {}, insert = false, isUpgrade = false) {
326
+ async addOrThrow(plugin, options = {}, insert = false, isUpgrade = false) {
301
327
  if (!isUpgrade && this.has(plugin)) {
302
328
  const name = typeof plugin === "string" ? plugin : plugin.name;
303
- this.app.log.warn(`plugin [${name}] added`);
304
- return;
329
+ throw new Error(`plugin [${name}] already added`);
305
330
  }
306
331
  if (!options.name && typeof plugin === "string") {
307
332
  options.name = plugin;
308
333
  }
309
- try {
310
- if (typeof plugin === "string" && options.name && !options.packageName) {
311
- const packageName = await _PluginManager.getPackageName(options.name);
312
- if (packageName) {
313
- options["packageName"] = packageName;
314
- }
334
+ if (typeof plugin === "string" && options.name && !options.packageName) {
335
+ const packageName = await _PluginManager.getPackageName(options.name);
336
+ if (packageName) {
337
+ options["packageName"] = packageName;
315
338
  }
316
- if (options.packageName) {
317
- const packageJson = await _PluginManager.getPackageJson(options.packageName);
318
- options["packageJson"] = packageJson;
319
- options["version"] = packageJson.version;
320
- }
321
- } catch (error) {
322
- this.app.log.error(error);
323
- console.error(error);
324
339
  }
325
- this.app.log.trace(`adding plugin [${options.name}]`, {
326
- method: "add",
327
- submodule: "plugin-manager",
328
- name: options.name,
329
- options
330
- });
331
- let P;
332
- try {
333
- P = await _PluginManager.resolvePlugin(options.packageName || plugin, isUpgrade, !!options.packageName);
334
- } catch (error) {
335
- this.app.log.warn("plugin not found", error);
336
- return;
340
+ if (options.packageName) {
341
+ const packageJson = await _PluginManager.getPackageJson(options.packageName);
342
+ options["packageJson"] = packageJson;
343
+ options["version"] = packageJson.version;
344
+ }
345
+ const P = await _PluginManager.resolvePlugin(options.packageName || plugin, isUpgrade, !!options.packageName);
346
+ if (!P) {
347
+ throw new Error(`plugin [${(options == null ? void 0 : options.name) || "unknown"}] load error`);
337
348
  }
338
349
  const instance = new P((0, import_helper.createAppProxy)(this.app), options);
339
350
  this.pluginInstances.set(P, instance);
@@ -344,12 +355,13 @@ const _PluginManager = class _PluginManager {
344
355
  this.pluginAliases.set(options.packageName, instance);
345
356
  }
346
357
  await instance.afterAdd();
347
- this.app.log.trace(`added plugin [${options.name}]`, {
348
- method: "add",
349
- submodule: "plugin-manager",
350
- name: instance.name,
351
- options: instance.options
352
- });
358
+ }
359
+ async add(plugin, options = {}, insert = false, isUpgrade = false) {
360
+ try {
361
+ await this.addOrThrow(plugin, options, insert, isUpgrade);
362
+ } catch (error) {
363
+ this.app.log.error(error);
364
+ }
353
365
  }
354
366
  /**
355
367
  * @internal
@@ -520,13 +532,13 @@ const _PluginManager = class _PluginManager {
520
532
  added[pluginName] = true;
521
533
  continue;
522
534
  }
523
- await this.add(pluginName);
535
+ await this.addOrThrow(pluginName);
524
536
  }
525
537
  for (const name of pluginNames) {
526
538
  const { name: pluginName } = await _PluginManager.parseName(name);
527
539
  const plugin = this.get(pluginName);
528
540
  if (!plugin) {
529
- throw new Error(`${pluginName} plugin does not exist`);
541
+ throw new PluginLoadError(pluginName);
530
542
  }
531
543
  if (added[pluginName]) {
532
544
  continue;
@@ -549,7 +561,7 @@ const _PluginManager = class _PluginManager {
549
561
  const { name: pluginName } = await _PluginManager.parseName(name);
550
562
  const plugin = this.get(pluginName);
551
563
  if (!plugin) {
552
- throw new Error(`${pluginName} plugin does not exist`);
564
+ throw new PluginLoadError(pluginName);
553
565
  }
554
566
  if (added[pluginName]) {
555
567
  continue;
@@ -574,7 +586,7 @@ const _PluginManager = class _PluginManager {
574
586
  const { name: pluginName } = await _PluginManager.parseName(name);
575
587
  const plugin = this.get(pluginName);
576
588
  if (!plugin) {
577
- throw new Error(`${pluginName} plugin does not exist`);
589
+ throw new PluginLoadError(pluginName);
578
590
  }
579
591
  if (plugin.enabled) {
580
592
  continue;
@@ -647,7 +659,7 @@ const _PluginManager = class _PluginManager {
647
659
  const { name: pluginName } = await _PluginManager.parseName(name2);
648
660
  const plugin = this.get(pluginName);
649
661
  if (!plugin) {
650
- throw new Error(`${pluginName} plugin does not exist`);
662
+ throw new PluginLoadError(pluginName);
651
663
  }
652
664
  if (!plugin.enabled) {
653
665
  continue;
@@ -763,7 +775,7 @@ const _PluginManager = class _PluginManager {
763
775
  if (process.env.VITEST) {
764
776
  return;
765
777
  }
766
- const file = (0, import_path.resolve)(process.cwd(), "storage/.upgrading");
778
+ const file = (0, import_utils.storagePathJoin)(".upgrading");
767
779
  this.app.log.debug("pending upgrade");
768
780
  await import_fs_extra.default.writeFile(file, "upgrading");
769
781
  }, "writeFile");
@@ -848,7 +860,7 @@ const _PluginManager = class _PluginManager {
848
860
  });
849
861
  return;
850
862
  }
851
- const file = (0, import_path.resolve)(process.cwd(), "storage/app-upgrading");
863
+ const file = (0, import_utils.storagePathJoin)("app-upgrading");
852
864
  await import_fs_extra.default.writeFile(file, "", "utf-8");
853
865
  await (0, import_helper.tsxRerunning)();
854
866
  await (0, import_execa.default)("yarn", ["nocobase", "pm2-restart"], {
@@ -1113,7 +1125,8 @@ const _PluginManager = class _PluginManager {
1113
1125
  }
1114
1126
  };
1115
1127
  __name(_PluginManager, "PluginManager");
1116
- __publicField(_PluginManager, "checkAndGetCompatible", import_utils2.checkAndGetCompatible);
1128
+ __publicField(_PluginManager, "compatibleCache", /* @__PURE__ */ new Map());
1129
+ __publicField(_PluginManager, "compatiblePending", /* @__PURE__ */ new Map());
1117
1130
  __publicField(_PluginManager, "parsedNames", {});
1118
1131
  let PluginManager = _PluginManager;
1119
1132
  var plugin_manager_default = PluginManager;
@@ -9,6 +9,7 @@
9
9
  import { AxiosRequestConfig } from 'axios';
10
10
  import { PluginManagerRepository } from './plugin-manager-repository';
11
11
  import { PluginData } from './types';
12
+ import Application from '../application';
12
13
  /**
13
14
  * get temp dir
14
15
  *
@@ -16,7 +17,6 @@ import { PluginData } from './types';
16
17
  * getTempDir() => '/tmp/nocobase'
17
18
  */
18
19
  export declare function getTempDir(): Promise<string>;
19
- export declare function getPluginStoragePath(): string;
20
20
  export declare function getLocalPluginPackagesPathArr(): string[];
21
21
  export declare function getStoragePluginDir(packageName: string): string;
22
22
  export declare function getLocalPluginDir(packageDirBasename: string): string;
@@ -112,4 +112,10 @@ export declare function checkAndGetCompatible(packageName: string): Promise<{
112
112
  depsCompatible: DepCompatible[];
113
113
  }>;
114
114
  export declare function getPluginBasePath(packageName: string): Promise<string>;
115
+ export declare function pmListSummary(app: Application): Promise<{
116
+ displayName: any;
117
+ packageName: any;
118
+ enabled: boolean;
119
+ description: any;
120
+ }[]>;
115
121
  export {};
@@ -59,12 +59,12 @@ __export(utils_exports, {
59
59
  getPackagesFromFiles: () => getPackagesFromFiles,
60
60
  getPluginBasePath: () => getPluginBasePath,
61
61
  getPluginInfoByNpm: () => getPluginInfoByNpm,
62
- getPluginStoragePath: () => getPluginStoragePath,
63
62
  getServerPackages: () => getServerPackages,
64
63
  getStoragePluginDir: () => getStoragePluginDir,
65
64
  getTempDir: () => getTempDir,
66
65
  isNotBuiltinModule: () => isNotBuiltinModule,
67
66
  isValidPackageName: () => isValidPackageName,
67
+ pmListSummary: () => pmListSummary,
68
68
  readJSONFileContent: () => readJSONFileContent,
69
69
  removePluginPackage: () => removePluginPackage,
70
70
  removeRequireCache: () => removeRequireCache,
@@ -88,17 +88,14 @@ var import_semver = __toESM(require("semver"));
88
88
  var import_clientStaticUtils = require("./clientStaticUtils");
89
89
  var import_constants = require("./constants");
90
90
  var import_deps = __toESM(require("./deps"));
91
+ var import_findPackageNames = require("./findPackageNames");
92
+ var import_plugin_manager = __toESM(require("./plugin-manager"));
91
93
  /* istanbul ignore next -- @preserve */
92
94
  async function getTempDir() {
93
95
  const temporaryDirectory = await import_fs_extra.default.realpath(import_os.default.tmpdir());
94
96
  return import_path.default.join(temporaryDirectory, import_constants.APP_NAME);
95
97
  }
96
98
  __name(getTempDir, "getTempDir");
97
- function getPluginStoragePath() {
98
- const pluginStoragePath = process.env.PLUGIN_STORAGE_PATH || import_constants.DEFAULT_PLUGIN_STORAGE_PATH;
99
- return import_path.default.isAbsolute(pluginStoragePath) ? pluginStoragePath : import_path.default.join(process.cwd(), pluginStoragePath);
100
- }
101
- __name(getPluginStoragePath, "getPluginStoragePath");
102
99
  function getLocalPluginPackagesPathArr() {
103
100
  const pluginPackagesPathArr = process.env.PLUGIN_PATH || import_constants.DEFAULT_PLUGIN_PATH;
104
101
  return pluginPackagesPathArr.split(",").map((pluginPackagesPath) => {
@@ -108,7 +105,7 @@ function getLocalPluginPackagesPathArr() {
108
105
  }
109
106
  __name(getLocalPluginPackagesPathArr, "getLocalPluginPackagesPathArr");
110
107
  function getStoragePluginDir(packageName) {
111
- const pluginStoragePath = getPluginStoragePath();
108
+ const pluginStoragePath = (0, import_utils.resolvePluginStoragePath)();
112
109
  return import_path.default.join(pluginStoragePath, packageName);
113
110
  }
114
111
  __name(getStoragePluginDir, "getStoragePluginDir");
@@ -340,7 +337,7 @@ async function updatePluginByCompressedFileUrl(options) {
340
337
  });
341
338
  if (!instance) {
342
339
  await removeTmpDir(tempFile, tempPackageContentDir);
343
- throw new Error(`plugin ${packageName} does not exist`);
340
+ throw new Error(`${packageName} does not exist`);
344
341
  }
345
342
  const { packageDir } = await copyTempPackageToStorageAndLinkToNodeModules(
346
343
  tempFile,
@@ -525,6 +522,33 @@ async function getPluginBasePath(packageName) {
525
522
  return import_path.default.dirname(import_path.default.dirname(file));
526
523
  }
527
524
  __name(getPluginBasePath, "getPluginBasePath");
525
+ async function pmListSummary(app) {
526
+ const plugins1 = await (0, import_findPackageNames.findBuiltInPlugins)();
527
+ const plugins2 = await (0, import_findPackageNames.findLocalPlugins)();
528
+ let enabledPlugins = [];
529
+ try {
530
+ enabledPlugins = (await app.pm.repository.find({
531
+ filter: {
532
+ enabled: true
533
+ }
534
+ })).map((item) => item.packageName);
535
+ } catch (error) {
536
+ }
537
+ const items = await Promise.all(
538
+ [...plugins1, ...plugins2].map(async (name) => {
539
+ const item = await import_plugin_manager.default.parseName(name);
540
+ const json = await import_plugin_manager.default.getPackageJson(item.packageName);
541
+ return {
542
+ displayName: json.displayName || name,
543
+ packageName: item.packageName,
544
+ enabled: enabledPlugins.includes(item.packageName),
545
+ description: json.description
546
+ };
547
+ })
548
+ );
549
+ return items;
550
+ }
551
+ __name(pmListSummary, "pmListSummary");
528
552
  // Annotate the CommonJS export names for ESM import in node:
529
553
  0 && (module.exports = {
530
554
  checkAndGetCompatible,
@@ -549,12 +573,12 @@ __name(getPluginBasePath, "getPluginBasePath");
549
573
  getPackagesFromFiles,
550
574
  getPluginBasePath,
551
575
  getPluginInfoByNpm,
552
- getPluginStoragePath,
553
576
  getServerPackages,
554
577
  getStoragePluginDir,
555
578
  getTempDir,
556
579
  isNotBuiltinModule,
557
580
  isValidPackageName,
581
+ pmListSummary,
558
582
  readJSONFileContent,
559
583
  removePluginPackage,
560
584
  removeRequireCache,