@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.
- package/LICENSE +201 -661
- package/README.md +79 -10
- package/lib/acl/available-action.js +1 -1
- package/lib/aes-encryptor.js +3 -2
- package/lib/app-supervisor/app-options-factory.d.ts +1 -0
- package/lib/app-supervisor/index.js +15 -1
- package/lib/app-supervisor/main-only-adapter.d.ts +1 -1
- package/lib/app-supervisor/main-only-adapter.js +17 -12
- package/lib/application.d.ts +1 -2
- package/lib/application.js +3 -24
- package/lib/audit-manager/index.d.ts +2 -0
- package/lib/audit-manager/index.js +5 -2
- package/lib/commands/ai.js +1 -6
- package/lib/commands/create-migration.js +1 -1
- package/lib/commands/install.js +0 -2
- package/lib/commands/pm.js +7 -0
- package/lib/commands/start.js +2 -5
- package/lib/commands/upgrade.js +0 -2
- package/lib/{ai/create-docs-index.d.ts → constants.d.ts} +1 -5
- package/lib/constants.js +36 -0
- package/lib/event-queue.js +1 -1
- package/lib/gateway/index.d.ts +15 -3
- package/lib/gateway/index.js +161 -20
- package/lib/gateway/static-file-security.d.ts +10 -0
- package/lib/gateway/static-file-security.js +69 -0
- package/lib/gateway/utils.d.ts +17 -0
- package/lib/gateway/utils.js +115 -0
- package/lib/helper.js +33 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.js +5 -4
- package/lib/locale/locale.d.ts +24 -0
- package/lib/locale/locale.js +29 -5
- package/lib/main-data-source.js +12 -5
- package/lib/plugin-manager/deps.js +3 -2
- package/lib/plugin-manager/findPackageNames.js +4 -2
- package/lib/plugin-manager/options/resource.d.ts +12 -1
- package/lib/plugin-manager/options/resource.js +212 -53
- package/lib/plugin-manager/plugin-manager.d.ts +7 -2
- package/lib/plugin-manager/plugin-manager.js +65 -56
- package/lib/plugin-manager/utils.d.ts +9 -1
- package/lib/plugin-manager/utils.js +68 -10
- package/lib/plugin.js +46 -2
- package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
- package/lib/pub-sub-manager/handler-manager.js +11 -0
- package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
- package/lib/swagger/app.d.ts +102 -0
- package/lib/swagger/app.js +124 -0
- package/lib/swagger/base.d.ts +244 -0
- package/lib/swagger/base.js +292 -0
- package/lib/swagger/collections.d.ts +996 -0
- package/lib/swagger/collections.js +1264 -0
- package/lib/swagger/index.d.ts +1774 -0
- package/lib/swagger/index.js +70 -0
- package/lib/swagger/pm.d.ts +462 -0
- package/lib/swagger/pm.js +422 -0
- package/lib/sync-message-manager.js +8 -1
- package/lib/worker-mode.d.ts +19 -0
- package/lib/worker-mode.js +67 -0
- package/package.json +19 -19
- package/lib/ai/create-docs-index.js +0 -892
- 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
|
|
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 (
|
|
275
|
-
const pluginDir = (0, import_path.resolve)(process.cwd(), "packages/plugins",
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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, "
|
|
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
|
|
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
|
|
98
|
-
|
|
99
|
-
|
|
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(
|
|
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 =
|
|
112
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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(
|
|
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("
|
|
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;
|