@nocobase/server 2.1.0-alpha.4 → 2.1.0-alpha.45

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 (63) 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/app-supervisor/app-options-factory.d.ts +1 -0
  6. package/lib/app-supervisor/index.d.ts +13 -5
  7. package/lib/app-supervisor/index.js +48 -13
  8. package/lib/app-supervisor/main-only-adapter.d.ts +4 -1
  9. package/lib/app-supervisor/main-only-adapter.js +24 -12
  10. package/lib/app-supervisor/types.d.ts +18 -3
  11. package/lib/application.d.ts +1 -2
  12. package/lib/application.js +3 -24
  13. package/lib/audit-manager/index.d.ts +2 -0
  14. package/lib/audit-manager/index.js +5 -2
  15. package/lib/commands/ai.js +1 -6
  16. package/lib/commands/create-migration.js +1 -1
  17. package/lib/commands/install.js +0 -2
  18. package/lib/commands/pm.js +7 -0
  19. package/lib/commands/start.js +2 -5
  20. package/lib/commands/upgrade.js +0 -2
  21. package/lib/{ai/create-docs-index.d.ts → constants.d.ts} +1 -5
  22. package/lib/constants.js +36 -0
  23. package/lib/event-queue.js +1 -1
  24. package/lib/gateway/index.d.ts +15 -3
  25. package/lib/gateway/index.js +161 -20
  26. package/lib/gateway/static-file-security.d.ts +10 -0
  27. package/lib/gateway/static-file-security.js +69 -0
  28. package/lib/gateway/utils.d.ts +17 -0
  29. package/lib/gateway/utils.js +115 -0
  30. package/lib/helper.js +33 -1
  31. package/lib/index.d.ts +3 -1
  32. package/lib/index.js +5 -4
  33. package/lib/locale/locale.d.ts +24 -0
  34. package/lib/locale/locale.js +29 -5
  35. package/lib/main-data-source.js +12 -5
  36. package/lib/plugin-manager/deps.js +3 -2
  37. package/lib/plugin-manager/findPackageNames.js +4 -2
  38. package/lib/plugin-manager/options/resource.d.ts +12 -1
  39. package/lib/plugin-manager/options/resource.js +212 -53
  40. package/lib/plugin-manager/plugin-manager.d.ts +7 -2
  41. package/lib/plugin-manager/plugin-manager.js +65 -56
  42. package/lib/plugin-manager/utils.d.ts +9 -1
  43. package/lib/plugin-manager/utils.js +68 -10
  44. package/lib/plugin.js +46 -2
  45. package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
  46. package/lib/pub-sub-manager/handler-manager.js +11 -0
  47. package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
  48. package/lib/swagger/app.d.ts +102 -0
  49. package/lib/swagger/app.js +124 -0
  50. package/lib/swagger/base.d.ts +244 -0
  51. package/lib/swagger/base.js +292 -0
  52. package/lib/swagger/collections.d.ts +996 -0
  53. package/lib/swagger/collections.js +1264 -0
  54. package/lib/swagger/index.d.ts +1774 -0
  55. package/lib/swagger/index.js +70 -0
  56. package/lib/swagger/pm.d.ts +462 -0
  57. package/lib/swagger/pm.js +422 -0
  58. package/lib/sync-message-manager.js +8 -1
  59. package/lib/worker-mode.d.ts +19 -0
  60. package/lib/worker-mode.js +67 -0
  61. package/package.json +19 -19
  62. package/lib/ai/create-docs-index.js +0 -892
  63. package/lib/swagger/index.json +0 -1569
@@ -39,45 +39,193 @@ 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_plugin_manager = __toESM(require("../plugin-manager"));
52
+ var import_utils2 = require("../utils");
53
+ var import_package = __toESM(require("../../../package.json"));
54
+ const PLUGIN_CLIENT_ENTRY_FILES = {
55
+ client: "dist/client/index.js",
56
+ "client-v2": "dist/client-v2/index.js"
57
+ };
58
+ const PLUGIN_CLIENT_MARKER_FILES = {
59
+ client: "client.js",
60
+ "client-v2": "client-v2.js"
61
+ };
62
+ function getAppDevPluginUrls() {
63
+ if (process.env.NOCOBASE_APP_DEV !== "true" || !process.env.NOCOBASE_APP_DEV_PLUGIN_URLS) {
64
+ return {};
65
+ }
66
+ try {
67
+ return JSON.parse(process.env.NOCOBASE_APP_DEV_PLUGIN_URLS);
68
+ } catch (error) {
69
+ return {};
70
+ }
71
+ }
72
+ __name(getAppDevPluginUrls, "getAppDevPluginUrls");
73
+ function getAppDevPluginDependencies(packageJson2, lane) {
74
+ const appDevPluginUrls = getAppDevPluginUrls();
75
+ const deps = {
76
+ ...packageJson2.dependencies,
77
+ ...packageJson2.peerDependencies,
78
+ ...packageJson2.devDependencies
79
+ };
80
+ return Object.keys(deps).filter(
81
+ (packageName) => {
82
+ var _a;
83
+ return ((_a = appDevPluginUrls[packageName]) == null ? void 0 : _a[lane]) || packageName.startsWith("@nocobase/plugin-") || packageName.startsWith("@nocobase/preset-");
84
+ }
85
+ );
86
+ }
87
+ __name(getAppDevPluginDependencies, "getAppDevPluginDependencies");
49
88
  const _PackageUrls = class _PackageUrls {
50
- static async get(packageName) {
51
- if (!this.items[packageName]) {
52
- this.items[packageName] = await this.fetch(packageName);
89
+ static clear() {
90
+ this.items = {};
91
+ }
92
+ static getCacheKey(packageName, lane) {
93
+ return `${lane}:${packageName}`;
94
+ }
95
+ static async get(packageName, lane = "client") {
96
+ const appDevUrl = this.getAppDevUrl(packageName, lane);
97
+ if (appDevUrl) {
98
+ return appDevUrl;
99
+ }
100
+ const cacheKey = this.getCacheKey(packageName, lane);
101
+ const cached = this.items[cacheKey];
102
+ if (cached) {
103
+ return cached;
104
+ }
105
+ const nextUrl = await this.fetch(packageName, lane);
106
+ if (nextUrl == null ? void 0 : nextUrl.includes("?hash=")) {
107
+ this.items[cacheKey] = nextUrl;
108
+ } else {
109
+ delete this.items[cacheKey];
53
110
  }
54
- return this.items[packageName];
111
+ return nextUrl;
55
112
  }
56
- static async fetch(packageName) {
57
- const PLUGIN_CLIENT_ENTRY_FILE = "dist/client/index.js";
113
+ static getAppDevUrl(packageName, lane) {
114
+ var _a;
115
+ return (_a = getAppDevPluginUrls()[packageName]) == null ? void 0 : _a[lane];
116
+ }
117
+ static async hasClientEntry(packageName, lane) {
118
+ if (this.getAppDevUrl(packageName, lane)) {
119
+ return true;
120
+ }
58
121
  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;
122
+ if (!await import_fs_extra.default.exists(pkgPath)) {
123
+ return false;
71
124
  }
125
+ return await import_fs_extra.default.exists(import_path.default.resolve(pkgPath, PLUGIN_CLIENT_MARKER_FILES[lane]));
126
+ }
127
+ static async fetch(packageName, lane = "client") {
128
+ const pluginClientEntryFile = PLUGIN_CLIENT_ENTRY_FILES[lane];
129
+ const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, packageName);
130
+ const pkgExists = await import_fs_extra.default.exists(pkgPath);
131
+ if (!pkgExists) {
132
+ return;
133
+ }
134
+ let t = "";
135
+ const dist = import_path.default.resolve(pkgPath, pluginClientEntryFile);
136
+ const distExists = await import_fs_extra.default.exists(dist);
137
+ if (distExists) {
138
+ const fsState = await import_fs_extra.default.stat(dist);
139
+ const appKey = process.env.APP_KEY || "";
140
+ let version = "";
141
+ try {
142
+ const pkgJson = await import_fs_extra.default.readJson(import_path.default.resolve(pkgPath, "package.json"));
143
+ if (pkgJson && typeof pkgJson.version === "string") {
144
+ version = pkgJson.version;
145
+ }
146
+ } catch (error) {
147
+ }
148
+ const appVersion = import_package.default.version;
149
+ const salt = process.env.PLUGIN_URL_HASH_SALT || "";
150
+ const hash = import_crypto.default.createHash("sha256").update(fsState.mtime.getTime() + appKey + version + appVersion + salt).digest("hex").slice(0, 8);
151
+ t = `?hash=${hash}`;
152
+ }
153
+ const cdnBaseUrl = process.env.CDN_BASE_URL.replace(/\/+$/, "");
154
+ const url = `${cdnBaseUrl}${"/static/plugins/"}${packageName}/${pluginClientEntryFile}${t}`;
155
+ return url;
72
156
  }
73
157
  };
74
158
  __name(_PackageUrls, "PackageUrls");
75
159
  __publicField(_PackageUrls, "items", {});
76
160
  let PackageUrls = _PackageUrls;
161
+ async function listEnabledPlugins(ctx, lane = "client") {
162
+ const pm = ctx.db.getRepository("applicationPlugins");
163
+ const items = await pm.find({
164
+ filter: {
165
+ enabled: true
166
+ }
167
+ });
168
+ const arr = [];
169
+ for (const item of items) {
170
+ if (lane === "client-v2" && !await PackageUrls.hasClientEntry(item.packageName, lane)) {
171
+ continue;
172
+ }
173
+ const url = await PackageUrls.get(item.packageName, lane);
174
+ const { name, packageName, options } = item.toJSON();
175
+ if (url) {
176
+ const entry = {
177
+ name,
178
+ packageName,
179
+ options,
180
+ url
181
+ };
182
+ if (PackageUrls.getAppDevUrl(packageName, lane)) {
183
+ const packageJson2 = await import_plugin_manager.default.getPackageJson(packageName);
184
+ entry.devMode = "esm";
185
+ entry.appDevDependencies = getAppDevPluginDependencies(packageJson2, lane);
186
+ }
187
+ if (lane === "client" && await PackageUrls.hasClientEntry(packageName, "client-v2")) {
188
+ const clientV2Url = await PackageUrls.get(packageName, "client-v2");
189
+ if (clientV2Url) {
190
+ entry.clientV2Url = clientV2Url;
191
+ }
192
+ }
193
+ arr.push(entry);
194
+ }
195
+ }
196
+ return arr;
197
+ }
198
+ __name(listEnabledPlugins, "listEnabledPlugins");
199
+ function normalizePmPluginKeys(filterByTk) {
200
+ if (typeof filterByTk === "string") {
201
+ return filterByTk.split(",").map((k) => k.trim()).filter(Boolean);
202
+ }
203
+ if (!Array.isArray(filterByTk) || filterByTk.some((item) => typeof item !== "string")) {
204
+ return [];
205
+ }
206
+ return filterByTk.flatMap(
207
+ (item) => item.split(",").map((k) => k.trim()).filter(Boolean)
208
+ );
209
+ }
210
+ __name(normalizePmPluginKeys, "normalizePmPluginKeys");
211
+ function coerceAwaitResponse(value) {
212
+ if (value === true || value === 1) {
213
+ return true;
214
+ }
215
+ if (typeof value === "string") {
216
+ const v = value.trim().toLowerCase();
217
+ return v === "true" || v === "1" || v === "yes";
218
+ }
219
+ return false;
220
+ }
221
+ __name(coerceAwaitResponse, "coerceAwaitResponse");
77
222
  var resource_default = {
78
223
  name: "pm",
79
224
  actions: {
80
225
  async add(ctx, next) {
226
+ if (process.env.DISABLE_PM_ADD === "true") {
227
+ ctx.throw(403, "The current environment does not allow adding plugins online");
228
+ }
81
229
  const app = ctx.app;
82
230
  const { values = {} } = ctx.action.params;
83
231
  if (values == null ? void 0 : values.packageName) {
@@ -93,12 +241,12 @@ var resource_default = {
93
241
  }
94
242
  app.runAsCLI(["pm", "add", values.packageName, ...args], { from: "user" });
95
243
  } else if (ctx.file) {
96
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
244
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
97
245
  try {
98
246
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
99
247
  } catch (error) {
100
248
  }
101
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
249
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
102
250
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
103
251
  app.runAsCLI(["pm", "add", tempFile], { from: "user" });
104
252
  } else if (values.compressedFileUrl) {
@@ -108,6 +256,9 @@ var resource_default = {
108
256
  await next();
109
257
  },
110
258
  async update(ctx, next) {
259
+ if (process.env.DISABLE_PM_ADD === "true") {
260
+ ctx.throw(403, "The current environment does not allow adding plugins online");
261
+ }
111
262
  const app = ctx.app;
112
263
  const values = ctx.action.params.values || {};
113
264
  const args = [];
@@ -122,12 +273,12 @@ var resource_default = {
122
273
  }
123
274
  if (ctx.file) {
124
275
  values.packageName = ctx.request.body.packageName;
125
- const tmpDir = import_path.default.resolve(process.cwd(), "storage", "tmp");
276
+ const tmpDir = (0, import_utils.storagePathJoin)("tmp");
126
277
  try {
127
278
  await import_fs.default.promises.mkdir(tmpDir, { recursive: true });
128
279
  } catch (error) {
129
280
  }
130
- const tempFile = import_path.default.join(process.cwd(), "storage/tmp", (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
281
+ const tempFile = import_path.default.join(tmpDir, (0, import_utils.uid)() + import_path.default.extname(ctx.file.originalname));
131
282
  await import_fs.default.promises.writeFile(tempFile, ctx.file.buffer, "binary");
132
283
  values.compressedFileUrl = tempFile;
133
284
  }
@@ -145,23 +296,40 @@ var resource_default = {
145
296
  await next();
146
297
  },
147
298
  async enable(ctx, next) {
148
- const { filterByTk } = ctx.action.params;
299
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
149
300
  const app = ctx.app;
150
- if (!filterByTk) {
301
+ const keys = normalizePmPluginKeys(filterByTk);
302
+ if (!keys.length) {
151
303
  ctx.throw(400, "plugin name invalid");
152
304
  }
153
- const keys = Array.isArray(filterByTk) ? filterByTk : [filterByTk];
154
- app.runAsCLI(["pm", "enable", ...keys], { from: "user" });
305
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
306
+ const argv = ["pm", "enable", ...keys];
307
+ if (awaitResponse) {
308
+ await app.runAsCLI(argv, { from: "user", throwError: true });
309
+ } else {
310
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
311
+ app.log.error(err);
312
+ });
313
+ }
155
314
  ctx.body = filterByTk;
156
315
  await next();
157
316
  },
158
317
  async disable(ctx, next) {
159
- const { filterByTk } = ctx.action.params;
160
- if (!filterByTk) {
318
+ const { filterByTk, awaitResponse: awaitResponseRaw } = ctx.action.params;
319
+ const app = ctx.app;
320
+ const keys = normalizePmPluginKeys(filterByTk);
321
+ if (!keys.length) {
161
322
  ctx.throw(400, "plugin name invalid");
162
323
  }
163
- const app = ctx.app;
164
- app.runAsCLI(["pm", "disable", filterByTk], { from: "user" });
324
+ const awaitResponse = coerceAwaitResponse(awaitResponseRaw);
325
+ const argv = ["pm", "disable", ...keys];
326
+ if (awaitResponse) {
327
+ await app.runAsCLI(argv, { from: "user", throwError: true });
328
+ } else {
329
+ void app.runAsCLI(argv, { from: "user" }).catch((err) => {
330
+ app.log.error(err);
331
+ });
332
+ }
165
333
  ctx.body = filterByTk;
166
334
  await next();
167
335
  },
@@ -176,6 +344,11 @@ var resource_default = {
176
344
  await next();
177
345
  },
178
346
  async list(ctx, next) {
347
+ const { mode } = ctx.action.params;
348
+ if (mode === "summary") {
349
+ ctx.body = await (0, import_utils2.pmListSummary)(ctx.app);
350
+ return next();
351
+ }
179
352
  const locale = ctx.getCurrentLocale();
180
353
  const pm = ctx.app.pm;
181
354
  const plugin = pm.get("nocobase");
@@ -183,29 +356,11 @@ var resource_default = {
183
356
  await next();
184
357
  },
185
358
  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();
359
+ ctx.body = await listEnabledPlugins(ctx, "client");
360
+ await next();
361
+ },
362
+ async listEnabledV2(ctx, next) {
363
+ ctx.body = await listEnabledPlugins(ctx, "client-v2");
209
364
  await next();
210
365
  },
211
366
  async get(ctx, next) {
@@ -221,3 +376,7 @@ var resource_default = {
221
376
  }
222
377
  }
223
378
  };
379
+ // Annotate the CommonJS export names for ESM import in node:
380
+ 0 && (module.exports = {
381
+ PackageUrls
382
+ });
@@ -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
  */
@@ -129,7 +155,11 @@ const _PluginManager = class _PluginManager {
129
155
  */
130
156
  static async getPackageJson(nameOrPkg) {
131
157
  const { packageName } = await this.parseName(nameOrPkg);
132
- const packageFile = (0, import_path.resolve)(process.env.NODE_MODULES_PATH, packageName, "package.json");
158
+ const nodeModulesPath = String(process.env.NODE_MODULES_PATH ?? "").trim();
159
+ if (!nodeModulesPath) {
160
+ throw new Error("NODE_MODULES_PATH is not configured");
161
+ }
162
+ const packageFile = (0, import_path.resolve)(nodeModulesPath, packageName, "package.json");
133
163
  if (!await import_fs_extra.default.exists(packageFile)) {
134
164
  throw new Error(`Cannot find plugin '${nameOrPkg}'`);
135
165
  }
@@ -271,69 +301,46 @@ const _PluginManager = class _PluginManager {
271
301
  }
272
302
  /* istanbul ignore next -- @preserve */
273
303
  async create(pluginName, options) {
274
- const createPlugin = /* @__PURE__ */ __name(async (name2) => {
275
- const pluginDir = (0, import_path.resolve)(process.cwd(), "packages/plugins", name2);
304
+ const createPlugin = /* @__PURE__ */ __name(async (name) => {
305
+ const pluginDir = (0, import_path.resolve)(process.cwd(), "packages/plugins", name);
276
306
  if (options == null ? void 0 : options.forceRecreate) {
277
307
  await import_fs_extra.default.rm(pluginDir, { recursive: true, force: true });
278
308
  }
279
- const { PluginGenerator } = require("@nocobase/cli/src/plugin-generator");
309
+ const { PluginGenerator } = require("@nocobase/cli-v1/src/plugin-generator");
280
310
  const generator = new PluginGenerator({
281
311
  cwd: process.cwd(),
282
312
  args: {},
283
313
  context: {
284
- name: name2
314
+ name
285
315
  }
286
316
  });
287
317
  await generator.run();
288
318
  }, "createPlugin");
289
319
  await createPlugin(pluginName);
290
320
  this.app.log.info("attempt to add the plugin to the app");
291
- const { name, packageName } = await _PluginManager.parseName(pluginName);
292
- const json = await _PluginManager.getPackageJson(packageName);
293
- this.app.log.info(`add plugin [${packageName}]`, {
294
- name,
295
- packageName,
296
- version: json.version
297
- });
298
- await (0, import_helper.tsxRerunning)();
299
321
  }
300
- async add(plugin, options = {}, insert = false, isUpgrade = false) {
322
+ async addOrThrow(plugin, options = {}, insert = false, isUpgrade = false) {
301
323
  if (!isUpgrade && this.has(plugin)) {
302
324
  const name = typeof plugin === "string" ? plugin : plugin.name;
303
- this.app.log.warn(`plugin [${name}] added`);
304
- return;
325
+ throw new Error(`plugin [${name}] already added`);
305
326
  }
306
327
  if (!options.name && typeof plugin === "string") {
307
328
  options.name = plugin;
308
329
  }
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
- }
315
- }
316
- if (options.packageName) {
317
- const packageJson = await _PluginManager.getPackageJson(options.packageName);
318
- options["packageJson"] = packageJson;
319
- options["version"] = packageJson.version;
330
+ if (typeof plugin === "string" && options.name && !options.packageName) {
331
+ const packageName = await _PluginManager.getPackageName(options.name);
332
+ if (packageName) {
333
+ options["packageName"] = packageName;
320
334
  }
321
- } catch (error) {
322
- this.app.log.error(error);
323
- console.error(error);
324
335
  }
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;
336
+ if (options.packageName) {
337
+ const packageJson = await _PluginManager.getPackageJson(options.packageName);
338
+ options["packageJson"] = packageJson;
339
+ options["version"] = packageJson.version;
340
+ }
341
+ const P = await _PluginManager.resolvePlugin(options.packageName || plugin, isUpgrade, !!options.packageName);
342
+ if (!P) {
343
+ throw new Error(`plugin [${(options == null ? void 0 : options.name) || "unknown"}] load error`);
337
344
  }
338
345
  const instance = new P((0, import_helper.createAppProxy)(this.app), options);
339
346
  this.pluginInstances.set(P, instance);
@@ -344,12 +351,13 @@ const _PluginManager = class _PluginManager {
344
351
  this.pluginAliases.set(options.packageName, instance);
345
352
  }
346
353
  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
- });
354
+ }
355
+ async add(plugin, options = {}, insert = false, isUpgrade = false) {
356
+ try {
357
+ await this.addOrThrow(plugin, options, insert, isUpgrade);
358
+ } catch (error) {
359
+ this.app.log.error(error);
360
+ }
353
361
  }
354
362
  /**
355
363
  * @internal
@@ -520,13 +528,13 @@ const _PluginManager = class _PluginManager {
520
528
  added[pluginName] = true;
521
529
  continue;
522
530
  }
523
- await this.add(pluginName);
531
+ await this.addOrThrow(pluginName);
524
532
  }
525
533
  for (const name of pluginNames) {
526
534
  const { name: pluginName } = await _PluginManager.parseName(name);
527
535
  const plugin = this.get(pluginName);
528
536
  if (!plugin) {
529
- throw new Error(`${pluginName} plugin does not exist`);
537
+ throw new PluginLoadError(pluginName);
530
538
  }
531
539
  if (added[pluginName]) {
532
540
  continue;
@@ -549,7 +557,7 @@ const _PluginManager = class _PluginManager {
549
557
  const { name: pluginName } = await _PluginManager.parseName(name);
550
558
  const plugin = this.get(pluginName);
551
559
  if (!plugin) {
552
- throw new Error(`${pluginName} plugin does not exist`);
560
+ throw new PluginLoadError(pluginName);
553
561
  }
554
562
  if (added[pluginName]) {
555
563
  continue;
@@ -574,7 +582,7 @@ const _PluginManager = class _PluginManager {
574
582
  const { name: pluginName } = await _PluginManager.parseName(name);
575
583
  const plugin = this.get(pluginName);
576
584
  if (!plugin) {
577
- throw new Error(`${pluginName} plugin does not exist`);
585
+ throw new PluginLoadError(pluginName);
578
586
  }
579
587
  if (plugin.enabled) {
580
588
  continue;
@@ -647,7 +655,7 @@ const _PluginManager = class _PluginManager {
647
655
  const { name: pluginName } = await _PluginManager.parseName(name2);
648
656
  const plugin = this.get(pluginName);
649
657
  if (!plugin) {
650
- throw new Error(`${pluginName} plugin does not exist`);
658
+ throw new PluginLoadError(pluginName);
651
659
  }
652
660
  if (!plugin.enabled) {
653
661
  continue;
@@ -763,7 +771,7 @@ const _PluginManager = class _PluginManager {
763
771
  if (process.env.VITEST) {
764
772
  return;
765
773
  }
766
- const file = (0, import_path.resolve)(process.cwd(), "storage/.upgrading");
774
+ const file = (0, import_utils.storagePathJoin)(".upgrading");
767
775
  this.app.log.debug("pending upgrade");
768
776
  await import_fs_extra.default.writeFile(file, "upgrading");
769
777
  }, "writeFile");
@@ -848,7 +856,7 @@ const _PluginManager = class _PluginManager {
848
856
  });
849
857
  return;
850
858
  }
851
- const file = (0, import_path.resolve)(process.cwd(), "storage/app-upgrading");
859
+ const file = (0, import_utils.storagePathJoin)("app-upgrading");
852
860
  await import_fs_extra.default.writeFile(file, "", "utf-8");
853
861
  await (0, import_helper.tsxRerunning)();
854
862
  await (0, import_execa.default)("yarn", ["nocobase", "pm2-restart"], {
@@ -1113,7 +1121,8 @@ const _PluginManager = class _PluginManager {
1113
1121
  }
1114
1122
  };
1115
1123
  __name(_PluginManager, "PluginManager");
1116
- __publicField(_PluginManager, "checkAndGetCompatible", import_utils2.checkAndGetCompatible);
1124
+ __publicField(_PluginManager, "compatibleCache", /* @__PURE__ */ new Map());
1125
+ __publicField(_PluginManager, "compatiblePending", /* @__PURE__ */ new Map());
1117
1126
  __publicField(_PluginManager, "parsedNames", {});
1118
1127
  let PluginManager = _PluginManager;
1119
1128
  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,8 @@ 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
+ export declare function assertSafePluginPackageName(packageName: string): void;
21
+ export declare function resolveSafeChildPath(baseDir: string, child: string): string;
20
22
  export declare function getLocalPluginPackagesPathArr(): string[];
21
23
  export declare function getStoragePluginDir(packageName: string): string;
22
24
  export declare function getLocalPluginDir(packageDirBasename: string): string;
@@ -112,4 +114,10 @@ export declare function checkAndGetCompatible(packageName: string): Promise<{
112
114
  depsCompatible: DepCompatible[];
113
115
  }>;
114
116
  export declare function getPluginBasePath(packageName: string): Promise<string>;
117
+ export declare function pmListSummary(app: Application): Promise<{
118
+ displayName: any;
119
+ packageName: any;
120
+ enabled: boolean;
121
+ description: any;
122
+ }[]>;
115
123
  export {};