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

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 (61) 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.js +15 -1
  7. package/lib/app-supervisor/main-only-adapter.d.ts +1 -1
  8. package/lib/app-supervisor/main-only-adapter.js +17 -12
  9. package/lib/application.d.ts +1 -2
  10. package/lib/application.js +3 -24
  11. package/lib/audit-manager/index.d.ts +2 -0
  12. package/lib/audit-manager/index.js +5 -2
  13. package/lib/commands/ai.js +1 -6
  14. package/lib/commands/create-migration.js +1 -1
  15. package/lib/commands/install.js +0 -2
  16. package/lib/commands/pm.js +7 -0
  17. package/lib/commands/start.js +2 -5
  18. package/lib/commands/upgrade.js +0 -2
  19. package/lib/{ai/create-docs-index.d.ts → constants.d.ts} +1 -5
  20. package/lib/constants.js +36 -0
  21. package/lib/event-queue.js +1 -1
  22. package/lib/gateway/index.d.ts +15 -3
  23. package/lib/gateway/index.js +161 -20
  24. package/lib/gateway/static-file-security.d.ts +10 -0
  25. package/lib/gateway/static-file-security.js +69 -0
  26. package/lib/gateway/utils.d.ts +17 -0
  27. package/lib/gateway/utils.js +115 -0
  28. package/lib/helper.js +33 -1
  29. package/lib/index.d.ts +3 -1
  30. package/lib/index.js +5 -4
  31. package/lib/locale/locale.d.ts +24 -0
  32. package/lib/locale/locale.js +29 -5
  33. package/lib/main-data-source.js +12 -5
  34. package/lib/plugin-manager/deps.js +3 -2
  35. package/lib/plugin-manager/findPackageNames.js +4 -2
  36. package/lib/plugin-manager/options/resource.d.ts +12 -1
  37. package/lib/plugin-manager/options/resource.js +212 -53
  38. package/lib/plugin-manager/plugin-manager.d.ts +7 -2
  39. package/lib/plugin-manager/plugin-manager.js +65 -56
  40. package/lib/plugin-manager/utils.d.ts +9 -1
  41. package/lib/plugin-manager/utils.js +68 -10
  42. package/lib/plugin.js +46 -2
  43. package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
  44. package/lib/pub-sub-manager/handler-manager.js +11 -0
  45. package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
  46. package/lib/swagger/app.d.ts +102 -0
  47. package/lib/swagger/app.js +124 -0
  48. package/lib/swagger/base.d.ts +244 -0
  49. package/lib/swagger/base.js +292 -0
  50. package/lib/swagger/collections.d.ts +996 -0
  51. package/lib/swagger/collections.js +1264 -0
  52. package/lib/swagger/index.d.ts +1774 -0
  53. package/lib/swagger/index.js +70 -0
  54. package/lib/swagger/pm.d.ts +462 -0
  55. package/lib/swagger/pm.js +422 -0
  56. package/lib/sync-message-manager.js +8 -1
  57. package/lib/worker-mode.d.ts +19 -0
  58. package/lib/worker-mode.js +67 -0
  59. package/package.json +19 -19
  60. package/lib/ai/create-docs-index.js +0 -892
  61. package/lib/swagger/index.json +0 -1569
@@ -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 {};
@@ -37,6 +37,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
38
  var utils_exports = {};
39
39
  __export(utils_exports, {
40
+ assertSafePluginPackageName: () => assertSafePluginPackageName,
40
41
  checkAndGetCompatible: () => checkAndGetCompatible,
41
42
  checkCompatible: () => checkCompatible,
42
43
  copyTempPackageToStorageAndLinkToNodeModules: () => copyTempPackageToStorageAndLinkToNodeModules,
@@ -59,18 +60,19 @@ __export(utils_exports, {
59
60
  getPackagesFromFiles: () => getPackagesFromFiles,
60
61
  getPluginBasePath: () => getPluginBasePath,
61
62
  getPluginInfoByNpm: () => getPluginInfoByNpm,
62
- getPluginStoragePath: () => getPluginStoragePath,
63
63
  getServerPackages: () => getServerPackages,
64
64
  getStoragePluginDir: () => getStoragePluginDir,
65
65
  getTempDir: () => getTempDir,
66
66
  isNotBuiltinModule: () => isNotBuiltinModule,
67
67
  isValidPackageName: () => isValidPackageName,
68
+ pmListSummary: () => pmListSummary,
68
69
  readJSONFileContent: () => readJSONFileContent,
69
70
  removePluginPackage: () => removePluginPackage,
70
71
  removeRequireCache: () => removeRequireCache,
71
72
  removeTmpDir: () => removeTmpDir,
72
73
  requireModule: () => requireModule,
73
74
  requireNoCache: () => requireNoCache,
75
+ resolveSafeChildPath: () => resolveSafeChildPath,
74
76
  updatePluginByCompressedFileUrl: () => updatePluginByCompressedFileUrl
75
77
  });
76
78
  module.exports = __toCommonJS(utils_exports);
@@ -88,17 +90,42 @@ var import_semver = __toESM(require("semver"));
88
90
  var import_clientStaticUtils = require("./clientStaticUtils");
89
91
  var import_constants = require("./constants");
90
92
  var import_deps = __toESM(require("./deps"));
93
+ var import_findPackageNames = require("./findPackageNames");
94
+ var import_plugin_manager = __toESM(require("./plugin-manager"));
91
95
  /* istanbul ignore next -- @preserve */
92
96
  async function getTempDir() {
93
97
  const temporaryDirectory = await import_fs_extra.default.realpath(import_os.default.tmpdir());
94
98
  return import_path.default.join(temporaryDirectory, import_constants.APP_NAME);
95
99
  }
96
100
  __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);
101
+ function assertSafePluginPackageName(packageName) {
102
+ if (!packageName || typeof packageName !== "string") {
103
+ throw new Error("Invalid plugin package name");
104
+ }
105
+ if (packageName.includes("\0")) {
106
+ throw new Error("Invalid plugin package name");
107
+ }
108
+ if (import_path.default.isAbsolute(packageName)) {
109
+ throw new Error("Invalid plugin package name");
110
+ }
111
+ if (packageName.includes("..") || packageName.includes("\\")) {
112
+ throw new Error("Invalid plugin package name");
113
+ }
114
+ const valid = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/i.test(packageName);
115
+ if (!valid) {
116
+ throw new Error("Invalid plugin package name");
117
+ }
118
+ }
119
+ __name(assertSafePluginPackageName, "assertSafePluginPackageName");
120
+ function resolveSafeChildPath(baseDir, child) {
121
+ const resolvedBase = import_path.default.resolve(baseDir);
122
+ const resolvedTarget = import_path.default.resolve(baseDir, child);
123
+ if (resolvedTarget !== resolvedBase && !resolvedTarget.startsWith(`${resolvedBase}${import_path.default.sep}`)) {
124
+ throw new Error("Path traversal detected");
125
+ }
126
+ return resolvedTarget;
100
127
  }
101
- __name(getPluginStoragePath, "getPluginStoragePath");
128
+ __name(resolveSafeChildPath, "resolveSafeChildPath");
102
129
  function getLocalPluginPackagesPathArr() {
103
130
  const pluginPackagesPathArr = process.env.PLUGIN_PATH || import_constants.DEFAULT_PLUGIN_PATH;
104
131
  return pluginPackagesPathArr.split(",").map((pluginPackagesPath) => {
@@ -108,8 +135,9 @@ function getLocalPluginPackagesPathArr() {
108
135
  }
109
136
  __name(getLocalPluginPackagesPathArr, "getLocalPluginPackagesPathArr");
110
137
  function getStoragePluginDir(packageName) {
111
- const pluginStoragePath = getPluginStoragePath();
112
- return import_path.default.join(pluginStoragePath, packageName);
138
+ const pluginStoragePath = (0, import_utils.resolvePluginStoragePath)();
139
+ assertSafePluginPackageName(packageName);
140
+ return resolveSafeChildPath(pluginStoragePath, packageName);
113
141
  }
114
142
  __name(getStoragePluginDir, "getStoragePluginDir");
115
143
  function getLocalPluginDir(packageDirBasename) {
@@ -121,7 +149,8 @@ function getLocalPluginDir(packageDirBasename) {
121
149
  }
122
150
  __name(getLocalPluginDir, "getLocalPluginDir");
123
151
  function getNodeModulesPluginDir(packageName) {
124
- return import_path.default.join(process.env.NODE_MODULES_PATH, packageName);
152
+ assertSafePluginPackageName(packageName);
153
+ return resolveSafeChildPath(process.env.NODE_MODULES_PATH, packageName);
125
154
  }
126
155
  __name(getNodeModulesPluginDir, "getNodeModulesPluginDir");
127
156
  function getAuthorizationHeaders(registry, authToken) {
@@ -340,7 +369,7 @@ async function updatePluginByCompressedFileUrl(options) {
340
369
  });
341
370
  if (!instance) {
342
371
  await removeTmpDir(tempFile, tempPackageContentDir);
343
- throw new Error(`plugin ${packageName} does not exist`);
372
+ throw new Error(`${packageName} does not exist`);
344
373
  }
345
374
  const { packageDir } = await copyTempPackageToStorageAndLinkToNodeModules(
346
375
  tempFile,
@@ -525,8 +554,36 @@ async function getPluginBasePath(packageName) {
525
554
  return import_path.default.dirname(import_path.default.dirname(file));
526
555
  }
527
556
  __name(getPluginBasePath, "getPluginBasePath");
557
+ async function pmListSummary(app) {
558
+ const plugins1 = await (0, import_findPackageNames.findBuiltInPlugins)();
559
+ const plugins2 = await (0, import_findPackageNames.findLocalPlugins)();
560
+ let enabledPlugins = [];
561
+ try {
562
+ enabledPlugins = (await app.pm.repository.find({
563
+ filter: {
564
+ enabled: true
565
+ }
566
+ })).map((item) => item.packageName);
567
+ } catch (error) {
568
+ }
569
+ const items = await Promise.all(
570
+ [...plugins1, ...plugins2].map(async (name) => {
571
+ const item = await import_plugin_manager.default.parseName(name);
572
+ const json = await import_plugin_manager.default.getPackageJson(item.packageName);
573
+ return {
574
+ displayName: json.displayName || name,
575
+ packageName: item.packageName,
576
+ enabled: enabledPlugins.includes(item.packageName),
577
+ description: json.description
578
+ };
579
+ })
580
+ );
581
+ return items;
582
+ }
583
+ __name(pmListSummary, "pmListSummary");
528
584
  // Annotate the CommonJS export names for ESM import in node:
529
585
  0 && (module.exports = {
586
+ assertSafePluginPackageName,
530
587
  checkAndGetCompatible,
531
588
  checkCompatible,
532
589
  copyTempPackageToStorageAndLinkToNodeModules,
@@ -549,17 +606,18 @@ __name(getPluginBasePath, "getPluginBasePath");
549
606
  getPackagesFromFiles,
550
607
  getPluginBasePath,
551
608
  getPluginInfoByNpm,
552
- getPluginStoragePath,
553
609
  getServerPackages,
554
610
  getStoragePluginDir,
555
611
  getTempDir,
556
612
  isNotBuiltinModule,
557
613
  isValidPackageName,
614
+ pmListSummary,
558
615
  readJSONFileContent,
559
616
  removePluginPackage,
560
617
  removeRequireCache,
561
618
  removeTmpDir,
562
619
  requireModule,
563
620
  requireNoCache,
621
+ resolveSafeChildPath,
564
622
  updatePluginByCompressedFileUrl
565
623
  });
package/lib/plugin.js CHANGED
@@ -206,6 +206,7 @@ const _Plugin = class _Plugin {
206
206
  return;
207
207
  }
208
208
  const toolsLoader = new import_ai.ToolsLoader(this.ai, {
209
+ pluginName: this.getName(),
209
210
  scan: {
210
211
  basePath,
211
212
  pattern: ["**/tools/**/*.ts", "**/tools/**/*.js", "!**/tools/**/*.d.ts", "**/tools/**/*/description.md"]
@@ -213,6 +214,37 @@ const _Plugin = class _Plugin {
213
214
  log: this.log
214
215
  });
215
216
  await toolsLoader.load();
217
+ const mcpLoader = new import_ai.MCPLoader(this.ai, {
218
+ pluginName: this.getName(),
219
+ scan: {
220
+ basePath,
221
+ pattern: ["mcp/*.ts", "mcp/*.js", "!mcp/*.d.ts"]
222
+ },
223
+ log: this.log
224
+ });
225
+ await mcpLoader.load();
226
+ const skillsLoader = new import_ai.SkillsLoader(this.ai, {
227
+ pluginName: this.getName(),
228
+ scan: { basePath, pattern: ["**/skills/**/SKILLS.md"] },
229
+ log: this.log
230
+ });
231
+ await skillsLoader.load();
232
+ const employeeLoader = new import_ai.AIEmployeeLoader(this.ai, {
233
+ pluginName: this.getName(),
234
+ scan: {
235
+ basePath,
236
+ pattern: [
237
+ "**/ai-employees/*.ts",
238
+ "**/ai-employees/*/index.ts",
239
+ "**/ai-employees/*.js",
240
+ "**/ai-employees/*/index.js",
241
+ "**/ai-employees/*/prompt.md",
242
+ "!**/ai-employees/**/*.d.ts"
243
+ ]
244
+ },
245
+ log: this.log
246
+ });
247
+ await employeeLoader.load();
216
248
  }
217
249
  /**
218
250
  * @deprecated
@@ -234,6 +266,18 @@ const _Plugin = class _Plugin {
234
266
  ...this.options
235
267
  };
236
268
  }
269
+ const langMap = {
270
+ "zh-CN": "cn/",
271
+ "en-US": "",
272
+ "ja-JP": "ja/",
273
+ "es-ES": "es/",
274
+ "pt-PT": "pt/",
275
+ "de-DE": "de",
276
+ "fr-FR": "fr/"
277
+ };
278
+ if (packageName.startsWith("@nocobase/plugin-")) {
279
+ packageJson.homepage = `https://v2.docs.nocobase.com/${langMap[locale] || ""}plugins/${packageName}`;
280
+ }
237
281
  const results = {
238
282
  ...this.options,
239
283
  keywords: packageJson.keywords,
@@ -241,7 +285,7 @@ const _Plugin = class _Plugin {
241
285
  changelogUrl: (0, import_plugin_manager.getExposeChangelogUrl)(packageName),
242
286
  displayName: packageJson[`displayName.${locale}`] || packageJson.displayName || name,
243
287
  description: packageJson[`description.${locale}`] || packageJson.description,
244
- homepage: packageJson[`homepage.${locale}`] || packageJson.homepage
288
+ homepage: packageJson.homepage
245
289
  };
246
290
  if (!options.withOutOpenFile) {
247
291
  const file = await import_fs.default.promises.realpath(
@@ -252,7 +296,7 @@ const _Plugin = class _Plugin {
252
296
  ...await (0, import_utils2.checkAndGetCompatible)(packageName),
253
297
  lastUpdated: (await import_fs.default.promises.stat(file)).ctime,
254
298
  file,
255
- updatable: file.startsWith(process.env.PLUGIN_STORAGE_PATH)
299
+ updatable: file.startsWith((0, import_utils.resolvePluginStoragePath)())
256
300
  };
257
301
  }
258
302
  return results;
@@ -29,6 +29,7 @@ export declare class HandlerManager {
29
29
  set(channel: string, callback: any, options: PubSubManagerSubscribeOptions): (wrappedMessage: any) => Promise<void>;
30
30
  get(channel: string, callback: any): any;
31
31
  delete(channel: string, callback: any): any;
32
+ cancelPendingDebounce(): void;
32
33
  reset(): void;
33
34
  each(callback: any): Promise<void>;
34
35
  }
@@ -129,7 +129,18 @@ const _HandlerManager = class _HandlerManager {
129
129
  headlerMap.delete(callback);
130
130
  return headler;
131
131
  }
132
+ cancelPendingDebounce() {
133
+ if (this.uniqueMessageHandlers) {
134
+ for (const handler of this.uniqueMessageHandlers.values()) {
135
+ if (typeof (handler == null ? void 0 : handler.cancel) === "function") {
136
+ handler.cancel();
137
+ }
138
+ }
139
+ this.uniqueMessageHandlers.clear();
140
+ }
141
+ }
132
142
  reset() {
143
+ this.cancelPendingDebounce();
133
144
  this.handlers = /* @__PURE__ */ new Map();
134
145
  this.uniqueMessageHandlers = /* @__PURE__ */ new Map();
135
146
  }
@@ -38,7 +38,7 @@ const createPubSubManager = /* @__PURE__ */ __name((app, options) => {
38
38
  app.on("afterStart", async () => {
39
39
  await pubSubManager.connect();
40
40
  });
41
- app.on("afterStop", async () => {
41
+ app.on("beforeStop", async () => {
42
42
  await pubSubManager.close();
43
43
  });
44
44
  return pubSubManager;
@@ -77,6 +77,7 @@ const _PubSubManager = class _PubSubManager {
77
77
  });
78
78
  }
79
79
  async close() {
80
+ this.handlerManager.cancelPendingDebounce();
80
81
  if (!this.adapter) {
81
82
  return;
82
83
  }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ declare const _default: {
10
+ readonly '/app:getLang': {
11
+ readonly get: {
12
+ readonly tags: readonly ["app"];
13
+ readonly summary: "Get the current application language";
14
+ readonly description: "Return the current locale used by the server.";
15
+ readonly parameters: readonly [];
16
+ readonly responses: {
17
+ readonly 200: {
18
+ readonly description: "OK";
19
+ readonly content: {
20
+ readonly 'application/json': {
21
+ readonly schema: {
22
+ readonly type: "string";
23
+ };
24
+ };
25
+ };
26
+ };
27
+ };
28
+ };
29
+ };
30
+ readonly '/app:getInfo': {
31
+ readonly get: {
32
+ readonly tags: readonly ["app"];
33
+ readonly summary: "Get application metadata";
34
+ readonly description: "Return basic application information, including version and environment-related metadata.";
35
+ readonly parameters: readonly [];
36
+ readonly responses: {
37
+ readonly 200: {
38
+ readonly description: "OK";
39
+ readonly content: {
40
+ readonly 'application/json': {
41
+ readonly schema: {
42
+ readonly type: "object";
43
+ readonly additionalProperties: true;
44
+ };
45
+ };
46
+ };
47
+ };
48
+ };
49
+ };
50
+ };
51
+ readonly '/app:getPlugins': {
52
+ readonly get: {
53
+ readonly tags: readonly ["app"];
54
+ readonly summary: "List loaded plugins";
55
+ readonly description: "Return plugin metadata for the current application runtime.";
56
+ readonly parameters: readonly [];
57
+ readonly responses: {
58
+ readonly 200: {
59
+ readonly description: "OK";
60
+ readonly content: {
61
+ readonly 'application/json': {
62
+ readonly schema: {
63
+ readonly type: "array";
64
+ readonly items: {
65
+ readonly type: "object";
66
+ readonly additionalProperties: true;
67
+ };
68
+ };
69
+ };
70
+ };
71
+ };
72
+ };
73
+ };
74
+ };
75
+ readonly '/app:restart': {
76
+ readonly post: {
77
+ readonly tags: readonly ["app"];
78
+ readonly summary: "Restart the application";
79
+ readonly description: "Trigger an application restart asynchronously.";
80
+ readonly parameters: readonly [];
81
+ readonly responses: {
82
+ readonly 200: {
83
+ readonly description: "OK";
84
+ };
85
+ };
86
+ };
87
+ };
88
+ readonly '/app:clearCache': {
89
+ readonly post: {
90
+ readonly tags: readonly ["app"];
91
+ readonly summary: "Clear application cache";
92
+ readonly description: "Clear server-side caches used by the current application instance.";
93
+ readonly parameters: readonly [];
94
+ readonly responses: {
95
+ readonly 200: {
96
+ readonly description: "OK";
97
+ };
98
+ };
99
+ };
100
+ };
101
+ };
102
+ export default _default;