@nocobase/server 2.1.0-beta.2 → 2.1.0-beta.20

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 (53) 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/audit-manager/index.d.ts +2 -0
  13. package/lib/audit-manager/index.js +5 -2
  14. package/lib/commands/create-migration.js +1 -1
  15. package/lib/commands/install.js +3 -1
  16. package/lib/commands/pm.js +7 -0
  17. package/lib/commands/start.js +2 -2
  18. package/lib/commands/upgrade.js +3 -1
  19. package/lib/event-queue.js +1 -1
  20. package/lib/gateway/index.d.ts +13 -3
  21. package/lib/gateway/index.js +137 -15
  22. package/lib/gateway/utils.d.ts +17 -0
  23. package/lib/gateway/utils.js +115 -0
  24. package/lib/helper.js +33 -1
  25. package/lib/index.d.ts +1 -0
  26. package/lib/index.js +2 -0
  27. package/lib/main-data-source.js +1 -1
  28. package/lib/plugin-manager/deps.js +2 -1
  29. package/lib/plugin-manager/options/resource.d.ts +11 -1
  30. package/lib/plugin-manager/options/resource.js +155 -53
  31. package/lib/plugin-manager/plugin-manager.d.ts +7 -2
  32. package/lib/plugin-manager/plugin-manager.js +56 -43
  33. package/lib/plugin-manager/utils.d.ts +7 -1
  34. package/lib/plugin-manager/utils.js +33 -9
  35. package/lib/plugin.js +33 -1
  36. package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
  37. package/lib/pub-sub-manager/handler-manager.js +11 -0
  38. package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
  39. package/lib/swagger/app.d.ts +102 -0
  40. package/lib/swagger/app.js +124 -0
  41. package/lib/swagger/base.d.ts +244 -0
  42. package/lib/swagger/base.js +292 -0
  43. package/lib/swagger/collections.d.ts +996 -0
  44. package/lib/swagger/collections.js +1264 -0
  45. package/lib/swagger/index.d.ts +1774 -0
  46. package/lib/swagger/index.js +70 -0
  47. package/lib/swagger/pm.d.ts +462 -0
  48. package/lib/swagger/pm.js +422 -0
  49. package/lib/sync-message-manager.js +8 -1
  50. package/lib/worker-mode.d.ts +19 -0
  51. package/lib/worker-mode.js +67 -0
  52. package/package.json +18 -18
  53. package/lib/swagger/index.json +0 -1569
@@ -39,45 +39,136 @@ 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);
53
72
  }
54
- return this.items[packageName];
73
+ return this.items[cacheKey];
55
74
  }
56
- static async fetch(packageName) {
57
- const PLUGIN_CLIENT_ENTRY_FILE = "dist/client/index.js";
75
+ static async hasClientEntry(packageName, lane) {
58
76
  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;
77
+ if (!await import_fs_extra.default.exists(pkgPath)) {
78
+ return false;
79
+ }
80
+ return await import_fs_extra.default.exists(import_path.default.resolve(pkgPath, PLUGIN_CLIENT_MARKER_FILES[lane]));
81
+ }
82
+ static async fetch(packageName, lane = "client") {
83
+ const pluginClientEntryFile = PLUGIN_CLIENT_ENTRY_FILES[lane];
84
+ const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, packageName);
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
+ if (typeof filterByTk === "string") {
144
+ return filterByTk.split(",").map((k) => k.trim()).filter(Boolean);
145
+ }
146
+ if (!Array.isArray(filterByTk) || filterByTk.some((item) => typeof item !== "string")) {
147
+ return [];
148
+ }
149
+ return filterByTk.flatMap(
150
+ (item) => item.split(",").map((k) => k.trim()).filter(Boolean)
151
+ );
152
+ }
153
+ __name(normalizePmPluginKeys, "normalizePmPluginKeys");
154
+ function coerceAwaitResponse(value) {
155
+ if (value === true || value === 1) {
156
+ return true;
157
+ }
158
+ if (typeof value === "string") {
159
+ const v = value.trim().toLowerCase();
160
+ return v === "true" || v === "1" || v === "yes";
161
+ }
162
+ return false;
163
+ }
164
+ __name(coerceAwaitResponse, "coerceAwaitResponse");
77
165
  var resource_default = {
78
166
  name: "pm",
79
167
  actions: {
80
168
  async add(ctx, next) {
169
+ if (process.env.DISABLE_PM_ADD === "true") {
170
+ ctx.throw(403, "The current environment does not allow adding plugins online");
171
+ }
81
172
  const app = ctx.app;
82
173
  const { values = {} } = ctx.action.params;
83
174
  if (values == null ? void 0 : values.packageName) {
@@ -93,12 +184,12 @@ var resource_default = {
93
184
  }
94
185
  app.runAsCLI(["pm", "add", values.packageName, ...args], { from: "user" });
95
186
  } else if (ctx.file) {
96
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
187
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
97
188
  try {
98
189
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
99
190
  } catch (error) {
100
191
  }
101
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
192
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
102
193
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
103
194
  app.runAsCLI(["pm", "add", tempFile], { from: "user" });
104
195
  } else if (values.compressedFileUrl) {
@@ -108,6 +199,9 @@ var resource_default = {
108
199
  await next();
109
200
  },
110
201
  async update(ctx, next) {
202
+ if (process.env.DISABLE_PM_ADD === "true") {
203
+ ctx.throw(403, "The current environment does not allow adding plugins online");
204
+ }
111
205
  const app = ctx.app;
112
206
  const values = ctx.action.params.values || {};
113
207
  const args = [];
@@ -122,12 +216,12 @@ var resource_default = {
122
216
  }
123
217
  if (ctx.file) {
124
218
  values.packageName = ctx.request.body.packageName;
125
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
219
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
126
220
  try {
127
221
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
128
222
  } catch (error) {
129
223
  }
130
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
224
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
131
225
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
132
226
  values.compressedFileUrl = tempFile;
133
227
  }
@@ -145,23 +239,40 @@ var resource_default = {
145
239
  await next();
146
240
  },
147
241
  async enable(ctx, next) {
148
- const { filterByTk } = ctx.action.params;
242
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
149
243
  const app = ctx.app;
150
- if (!filterByTk) {
244
+ const keys = normalizePmPluginKeys(filterByTk);
245
+ if (!keys.length) {
151
246
  ctx.throw(400, "plugin name invalid");
152
247
  }
153
- const keys = Array.isArray(filterByTk) ? filterByTk : [filterByTk];
154
- app.runAsCLI(["pm", "enable", ...keys], { from: "user" });
248
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
249
+ const argv = ["pm", "enable", ...keys];
250
+ if (awaitResponse) {
251
+ await app.runAsCLI(argv, { from: "user", throwError: true });
252
+ } else {
253
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
254
+ app.log.error(err);
255
+ });
256
+ }
155
257
  ctx.body = filterByTk;
156
258
  await next();
157
259
  },
158
260
  async disable(ctx, next) {
159
- const { filterByTk } = ctx.action.params;
160
- if (!filterByTk) {
261
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
262
+ const app = ctx.app;
263
+ const keys = normalizePmPluginKeys(filterByTk);
264
+ if (!keys.length) {
161
265
  ctx.throw(400, "plugin name invalid");
162
266
  }
163
- const app = ctx.app;
164
- app.runAsCLI(["pm", "disable", filterByTk], { from: "user" });
267
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
268
+ const argv = ["pm", "disable", ...keys];
269
+ if (awaitResponse) {
270
+ await app.runAsCLI(argv, { from: "user", throwError: true });
271
+ } else {
272
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
273
+ app.log.error(err);
274
+ });
275
+ }
165
276
  ctx.body = filterByTk;
166
277
  await next();
167
278
  },
@@ -176,6 +287,11 @@ var resource_default = {
176
287
  await next();
177
288
  },
178
289
  async list(ctx, next) {
290
+ const { mode } = ctx.action.params;
291
+ if (mode === "summary") {
292
+ ctx.body = await (0, import_utils2.pmListSummary)(ctx.app);
293
+ return next();
294
+ }
179
295
  const locale = ctx.getCurrentLocale();
180
296
  const pm = ctx.app.pm;
181
297
  const plugin = pm.get("nocobase");
@@ -183,29 +299,11 @@ var resource_default = {
183
299
  await next();
184
300
  },
185
301
  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();
302
+ ctx.body = await listEnabledPlugins(ctx, "client");
303
+ await next();
304
+ },
305
+ async listEnabledV2(ctx, next) {
306
+ ctx.body = await listEnabledPlugins(ctx, "client-v2");
209
307
  await next();
210
308
  },
211
309
  async get(ctx, next) {
@@ -221,3 +319,7 @@ var resource_default = {
221
319
  }
222
320
  }
223
321
  };
322
+ // Annotate the CommonJS export names for ESM import in node:
323
+ 0 && (module.exports = {
324
+ PackageUrls
325
+ });
@@ -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,