@lark-apaas/nestjs-capability 0.0.1-alpha.9 → 0.1.0
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/dist/index.cjs +387 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -10
- package/dist/index.d.ts +147 -10
- package/dist/index.js +383 -136
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
|
|
10
4
|
// src/interfaces/error-codes.ts
|
|
11
5
|
var ErrorCodes = {
|
|
@@ -37,9 +31,9 @@ var TemplateEngineService = class {
|
|
|
37
31
|
__name(this, "TemplateEngineService");
|
|
38
32
|
}
|
|
39
33
|
// 匹配 {{input.xxx}} 或 {{input.xxx.yyy}} 表达式
|
|
40
|
-
EXPR_REGEX = /\{\{input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\}\}/g;
|
|
34
|
+
EXPR_REGEX = /\{\{\s*input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*\s*)\}\}/g;
|
|
41
35
|
// 匹配整串单个表达式
|
|
42
|
-
WHOLE_STRING_EXPR_REGEX = /^\{\{input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\}\}$/;
|
|
36
|
+
WHOLE_STRING_EXPR_REGEX = /^\{\{\s*input\.([a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)\s*\}\}$/;
|
|
43
37
|
resolve(template, input) {
|
|
44
38
|
if (typeof template === "string") {
|
|
45
39
|
return this.resolveString(template, input);
|
|
@@ -98,6 +92,8 @@ TemplateEngineService = _ts_decorate([
|
|
|
98
92
|
|
|
99
93
|
// src/services/plugin-loader.service.ts
|
|
100
94
|
import { Injectable as Injectable2, Logger } from "@nestjs/common";
|
|
95
|
+
import { createRequire } from "module";
|
|
96
|
+
import { pathToFileURL } from "url";
|
|
101
97
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
102
98
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
103
99
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -105,13 +101,16 @@ function _ts_decorate2(decorators, target, key, desc) {
|
|
|
105
101
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
106
102
|
}
|
|
107
103
|
__name(_ts_decorate2, "_ts_decorate");
|
|
104
|
+
var require2 = createRequire(import.meta.url);
|
|
108
105
|
var PluginNotFoundError = class extends Error {
|
|
109
106
|
static {
|
|
110
107
|
__name(this, "PluginNotFoundError");
|
|
111
108
|
}
|
|
109
|
+
pluginKey;
|
|
112
110
|
constructor(pluginKey) {
|
|
113
111
|
super(`Plugin not found: ${pluginKey}`);
|
|
114
112
|
this.name = "PluginNotFoundError";
|
|
113
|
+
this.pluginKey = pluginKey;
|
|
115
114
|
}
|
|
116
115
|
};
|
|
117
116
|
var PluginLoadError = class extends Error {
|
|
@@ -129,6 +128,8 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
129
128
|
}
|
|
130
129
|
logger = new Logger(_PluginLoaderService.name);
|
|
131
130
|
pluginInstances = /* @__PURE__ */ new Map();
|
|
131
|
+
/** 记录每个插件的加载版本(时间戳),用于 ESM 缓存绕过 */
|
|
132
|
+
pluginVersions = /* @__PURE__ */ new Map();
|
|
132
133
|
async loadPlugin(pluginKey) {
|
|
133
134
|
const cached = this.pluginInstances.get(pluginKey);
|
|
134
135
|
if (cached) {
|
|
@@ -137,7 +138,12 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
137
138
|
}
|
|
138
139
|
this.logger.log(`Loading plugin: ${pluginKey}`);
|
|
139
140
|
try {
|
|
140
|
-
const
|
|
141
|
+
const resolvedPath = require2.resolve(pluginKey);
|
|
142
|
+
const version = this.pluginVersions.get(pluginKey) ?? 0;
|
|
143
|
+
const fileUrl = pathToFileURL(resolvedPath).href;
|
|
144
|
+
const importPath = version > 0 ? `${fileUrl}?v=${version}` : fileUrl;
|
|
145
|
+
const mod = await import(importPath);
|
|
146
|
+
const pluginPackage = mod.default ?? mod;
|
|
141
147
|
if (typeof pluginPackage.create !== "function") {
|
|
142
148
|
throw new PluginLoadError(pluginKey, "Plugin does not export create() function");
|
|
143
149
|
}
|
|
@@ -154,21 +160,68 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
154
160
|
}
|
|
155
161
|
isPluginInstalled(pluginKey) {
|
|
156
162
|
try {
|
|
157
|
-
|
|
163
|
+
require2.resolve(pluginKey);
|
|
158
164
|
return true;
|
|
159
165
|
} catch {
|
|
160
166
|
return false;
|
|
161
167
|
}
|
|
162
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* 清除插件缓存
|
|
171
|
+
* - 清除应用层 pluginInstances 缓存
|
|
172
|
+
* - 清除 Node.js CJS 模块缓存(require.cache)
|
|
173
|
+
* - 更新版本号,下次 import 时绕过 ESM 缓存
|
|
174
|
+
* @param pluginKey - 插件标识,不传则清除所有
|
|
175
|
+
*/
|
|
163
176
|
clearCache(pluginKey) {
|
|
164
177
|
if (pluginKey) {
|
|
165
178
|
this.pluginInstances.delete(pluginKey);
|
|
179
|
+
this.clearNodeModuleCache(pluginKey);
|
|
180
|
+
this.pluginVersions.set(pluginKey, Date.now());
|
|
166
181
|
this.logger.log(`Cleared cache for plugin: ${pluginKey}`);
|
|
167
182
|
} else {
|
|
183
|
+
for (const key of this.pluginInstances.keys()) {
|
|
184
|
+
this.clearNodeModuleCache(key);
|
|
185
|
+
this.pluginVersions.set(key, Date.now());
|
|
186
|
+
}
|
|
168
187
|
this.pluginInstances.clear();
|
|
169
188
|
this.logger.log("Cleared all plugin caches");
|
|
170
189
|
}
|
|
171
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* 清除 CJS 模块缓存
|
|
193
|
+
*/
|
|
194
|
+
clearNodeModuleCache(pluginKey) {
|
|
195
|
+
try {
|
|
196
|
+
const resolvedPath = require2.resolve(pluginKey);
|
|
197
|
+
const mod = require2.cache[resolvedPath];
|
|
198
|
+
if (mod) {
|
|
199
|
+
this.clearModuleAndChildren(mod, pluginKey);
|
|
200
|
+
}
|
|
201
|
+
delete require2.cache[resolvedPath];
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* 递归清除子模块缓存
|
|
207
|
+
*/
|
|
208
|
+
clearModuleAndChildren(mod, pluginKey) {
|
|
209
|
+
const pluginScope = pluginKey.startsWith("@") ? pluginKey.split("/").slice(0, 2).join("/") : pluginKey;
|
|
210
|
+
mod.children.forEach((child) => {
|
|
211
|
+
if (child.filename.includes(`node_modules/${pluginScope}`)) {
|
|
212
|
+
this.clearModuleAndChildren(child, pluginKey);
|
|
213
|
+
delete require2.cache[child.filename];
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* 强制重新加载插件
|
|
219
|
+
* @param pluginKey - 插件标识
|
|
220
|
+
*/
|
|
221
|
+
async reloadPlugin(pluginKey) {
|
|
222
|
+
this.clearCache(pluginKey);
|
|
223
|
+
return this.loadPlugin(pluginKey);
|
|
224
|
+
}
|
|
172
225
|
};
|
|
173
226
|
PluginLoaderService = _ts_decorate2([
|
|
174
227
|
Injectable2()
|
|
@@ -179,6 +232,7 @@ import { Injectable as Injectable3, Logger as Logger2, Inject } from "@nestjs/co
|
|
|
179
232
|
import { RequestContextService, PLATFORM_HTTP_CLIENT } from "@lark-apaas/nestjs-common";
|
|
180
233
|
import * as fs from "fs";
|
|
181
234
|
import * as path from "path";
|
|
235
|
+
import * as chokidar from "chokidar";
|
|
182
236
|
|
|
183
237
|
// src/utils/log-utils.ts
|
|
184
238
|
var DEFAULT_MAX_LENGTH = 1e3;
|
|
@@ -200,6 +254,43 @@ function stringifyForLog(value, maxLength = DEFAULT_MAX_LENGTH) {
|
|
|
200
254
|
}
|
|
201
255
|
__name(stringifyForLog, "stringifyForLog");
|
|
202
256
|
|
|
257
|
+
// src/utils/migration-adaptor.ts
|
|
258
|
+
async function migrationAdaptor(promise) {
|
|
259
|
+
try {
|
|
260
|
+
const result = await promise;
|
|
261
|
+
return {
|
|
262
|
+
code: 0,
|
|
263
|
+
data: {
|
|
264
|
+
output: result,
|
|
265
|
+
outcome: "success"
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
} catch (error) {
|
|
269
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
270
|
+
const appStatusCode = error instanceof Error && "code" in error ? String(error.code) : "EXECUTION_ERROR";
|
|
271
|
+
return {
|
|
272
|
+
code: -1,
|
|
273
|
+
data: {
|
|
274
|
+
outcome: "error",
|
|
275
|
+
failureOutput: {
|
|
276
|
+
response: {
|
|
277
|
+
status: {
|
|
278
|
+
protocolStatusCode: "500",
|
|
279
|
+
appStatusCode
|
|
280
|
+
},
|
|
281
|
+
body: JSON.stringify({
|
|
282
|
+
error: errorMessage,
|
|
283
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
message: errorMessage
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
__name(migrationAdaptor, "migrationAdaptor");
|
|
293
|
+
|
|
203
294
|
// src/services/capability.service.ts
|
|
204
295
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
205
296
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -222,18 +313,24 @@ var CapabilityNotFoundError = class extends Error {
|
|
|
222
313
|
static {
|
|
223
314
|
__name(this, "CapabilityNotFoundError");
|
|
224
315
|
}
|
|
316
|
+
capabilityId;
|
|
225
317
|
constructor(capabilityId) {
|
|
226
318
|
super(`Capability not found: ${capabilityId}`);
|
|
227
319
|
this.name = "CapabilityNotFoundError";
|
|
320
|
+
this.capabilityId = capabilityId;
|
|
228
321
|
}
|
|
229
322
|
};
|
|
230
323
|
var ActionNotFoundError = class extends Error {
|
|
231
324
|
static {
|
|
232
325
|
__name(this, "ActionNotFoundError");
|
|
233
326
|
}
|
|
327
|
+
pluginKey;
|
|
328
|
+
actionName;
|
|
234
329
|
constructor(pluginKey, actionName) {
|
|
235
330
|
super(`Action '${actionName}' not found in plugin ${pluginKey}`);
|
|
236
331
|
this.name = "ActionNotFoundError";
|
|
332
|
+
this.pluginKey = pluginKey;
|
|
333
|
+
this.actionName = actionName;
|
|
237
334
|
}
|
|
238
335
|
};
|
|
239
336
|
var CapabilityService = class _CapabilityService {
|
|
@@ -246,7 +343,11 @@ var CapabilityService = class _CapabilityService {
|
|
|
246
343
|
templateEngineService;
|
|
247
344
|
logger = new Logger2(_CapabilityService.name);
|
|
248
345
|
capabilities = /* @__PURE__ */ new Map();
|
|
346
|
+
/** 文件路径到 capability id 的映射,用于文件删除时查找 */
|
|
347
|
+
filePathToId = /* @__PURE__ */ new Map();
|
|
249
348
|
capabilitiesDir;
|
|
349
|
+
fileWatcher = null;
|
|
350
|
+
options = {};
|
|
250
351
|
constructor(requestContextService, platformHttpClient, pluginLoaderService, templateEngineService) {
|
|
251
352
|
this.requestContextService = requestContextService;
|
|
252
353
|
this.platformHttpClient = platformHttpClient;
|
|
@@ -255,12 +356,140 @@ var CapabilityService = class _CapabilityService {
|
|
|
255
356
|
const isDev = process.env.NODE_ENV === "development";
|
|
256
357
|
this.capabilitiesDir = path.join(process.cwd(), isDev ? "server/capabilities" : "capabilities");
|
|
257
358
|
}
|
|
359
|
+
/**
|
|
360
|
+
* 设置模块配置
|
|
361
|
+
*/
|
|
362
|
+
setOptions(options) {
|
|
363
|
+
this.options = options;
|
|
364
|
+
if (options.capabilitiesDir) {
|
|
365
|
+
this.capabilitiesDir = options.capabilitiesDir;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
258
368
|
setCapabilitiesDir(dir) {
|
|
259
369
|
this.capabilitiesDir = dir;
|
|
260
370
|
}
|
|
261
371
|
async onModuleInit() {
|
|
262
372
|
await this.loadCapabilities();
|
|
373
|
+
if (this.options.enableWatching) {
|
|
374
|
+
this.startWatching();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async onModuleDestroy() {
|
|
378
|
+
this.stopWatching();
|
|
379
|
+
}
|
|
380
|
+
// ==================== 文件监听相关方法 ====================
|
|
381
|
+
/**
|
|
382
|
+
* 启动文件监听(沙箱环境自动调用)
|
|
383
|
+
*/
|
|
384
|
+
startWatching() {
|
|
385
|
+
if (this.fileWatcher) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (!fs.existsSync(this.capabilitiesDir)) {
|
|
389
|
+
this.logger.warn(`Cannot start watching: directory not found: ${this.capabilitiesDir}`);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
const pattern = path.join(this.capabilitiesDir, "*.json");
|
|
393
|
+
const debounce = this.options.watchDebounce ?? 300;
|
|
394
|
+
this.logger.log(`Starting file watcher: ${pattern}`);
|
|
395
|
+
this.fileWatcher = chokidar.watch(pattern, {
|
|
396
|
+
persistent: true,
|
|
397
|
+
ignoreInitial: true,
|
|
398
|
+
awaitWriteFinish: {
|
|
399
|
+
// 等待写入完成
|
|
400
|
+
stabilityThreshold: debounce,
|
|
401
|
+
pollInterval: 100
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
this.fileWatcher.on("add", (filePath) => this.handleFileAdd(filePath)).on("change", (filePath) => this.handleFileChange(filePath)).on("unlink", (filePath) => this.handleFileUnlink(filePath)).on("error", (error) => this.logger.error("File watcher error:", error));
|
|
405
|
+
this.logger.log("File watcher started");
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* 停止文件监听
|
|
409
|
+
*/
|
|
410
|
+
stopWatching() {
|
|
411
|
+
if (this.fileWatcher) {
|
|
412
|
+
this.fileWatcher.close();
|
|
413
|
+
this.fileWatcher = null;
|
|
414
|
+
this.logger.log("File watcher stopped");
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* 重新加载所有能力配置
|
|
419
|
+
*/
|
|
420
|
+
async reloadAllCapabilities() {
|
|
421
|
+
this.capabilities.clear();
|
|
422
|
+
this.filePathToId.clear();
|
|
423
|
+
await this.loadCapabilities();
|
|
424
|
+
}
|
|
425
|
+
handleFileAdd(filePath) {
|
|
426
|
+
this.logger.log(`Capability file added: ${filePath}`);
|
|
427
|
+
try {
|
|
428
|
+
this.loadCapabilityFromFile(filePath);
|
|
429
|
+
const capabilityId = this.filePathToId.get(filePath);
|
|
430
|
+
if (capabilityId) {
|
|
431
|
+
const config = this.capabilities.get(capabilityId);
|
|
432
|
+
if (config?.pluginKey) {
|
|
433
|
+
this.pluginLoaderService.clearCache(config.pluginKey);
|
|
434
|
+
this.logger.log(`Cleared plugin cache for new capability: ${config.pluginKey}`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
} catch (error) {
|
|
438
|
+
this.logger.error(`Failed to load new capability: ${filePath}`, error);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
handleFileChange(filePath) {
|
|
442
|
+
this.logger.log(`Capability file changed: ${filePath}`);
|
|
443
|
+
try {
|
|
444
|
+
this.reloadCapabilityFromFile(filePath);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
this.logger.error(`Failed to reload capability: ${filePath}`, error);
|
|
447
|
+
}
|
|
263
448
|
}
|
|
449
|
+
handleFileUnlink(filePath) {
|
|
450
|
+
this.logger.log(`Capability file removed: ${filePath}`);
|
|
451
|
+
this.removeCapabilityByFile(filePath);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* 从文件加载单个能力配置
|
|
455
|
+
*/
|
|
456
|
+
loadCapabilityFromFile(filePath) {
|
|
457
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
458
|
+
const config = JSON.parse(content);
|
|
459
|
+
if (!config.id) {
|
|
460
|
+
this.logger.warn(`Skipping capability without id: ${filePath}`);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
this.capabilities.set(config.id, config);
|
|
464
|
+
this.filePathToId.set(filePath, config.id);
|
|
465
|
+
this.logger.log(`Loaded capability: ${config.id} (${config.name})`);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* 重新加载单个能力配置
|
|
469
|
+
*/
|
|
470
|
+
reloadCapabilityFromFile(filePath) {
|
|
471
|
+
const oldId = this.filePathToId.get(filePath);
|
|
472
|
+
if (oldId) {
|
|
473
|
+
const oldConfig = this.capabilities.get(oldId);
|
|
474
|
+
if (oldConfig) {
|
|
475
|
+
this.pluginLoaderService.clearCache(oldConfig.pluginKey);
|
|
476
|
+
}
|
|
477
|
+
this.capabilities.delete(oldId);
|
|
478
|
+
}
|
|
479
|
+
this.loadCapabilityFromFile(filePath);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* 根据文件路径移除能力配置
|
|
483
|
+
*/
|
|
484
|
+
removeCapabilityByFile(filePath) {
|
|
485
|
+
const capabilityId = this.filePathToId.get(filePath);
|
|
486
|
+
if (capabilityId) {
|
|
487
|
+
this.capabilities.delete(capabilityId);
|
|
488
|
+
this.filePathToId.delete(filePath);
|
|
489
|
+
this.logger.log(`Removed capability: ${capabilityId}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// ==================== 原有方法 ====================
|
|
264
493
|
async loadCapabilities() {
|
|
265
494
|
this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);
|
|
266
495
|
if (!fs.existsSync(this.capabilitiesDir)) {
|
|
@@ -271,14 +500,7 @@ var CapabilityService = class _CapabilityService {
|
|
|
271
500
|
for (const file of files) {
|
|
272
501
|
try {
|
|
273
502
|
const filePath = path.join(this.capabilitiesDir, file);
|
|
274
|
-
|
|
275
|
-
const config = JSON.parse(content);
|
|
276
|
-
if (!config.id) {
|
|
277
|
-
this.logger.warn(`Skipping capability without id: ${file}`);
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
this.capabilities.set(config.id, config);
|
|
281
|
-
this.logger.log(`Loaded capability: ${config.id} (${config.name})`);
|
|
503
|
+
this.loadCapabilityFromFile(filePath);
|
|
282
504
|
} catch (error) {
|
|
283
505
|
this.logger.error(`Failed to load capability from ${file}:`, error);
|
|
284
506
|
}
|
|
@@ -554,7 +776,8 @@ CapabilityService = _ts_decorate3([
|
|
|
554
776
|
], CapabilityService);
|
|
555
777
|
|
|
556
778
|
// src/controllers/debug.controller.ts
|
|
557
|
-
import { Controller, Post, Get, Param, Body, Res,
|
|
779
|
+
import { Controller, Post, Get, Param, Body, Res, HttpStatus, Logger as Logger3 } from "@nestjs/common";
|
|
780
|
+
import { ApiExcludeController } from "@nestjs/swagger";
|
|
558
781
|
function _ts_decorate4(decorators, target, key, desc) {
|
|
559
782
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
560
783
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -585,19 +808,27 @@ var DebugController = class _DebugController {
|
|
|
585
808
|
this.pluginLoaderService = pluginLoaderService;
|
|
586
809
|
this.templateEngineService = templateEngineService;
|
|
587
810
|
}
|
|
588
|
-
list() {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
811
|
+
list(res) {
|
|
812
|
+
try {
|
|
813
|
+
const capabilities = this.capabilityService.listCapabilities();
|
|
814
|
+
res.status(HttpStatus.OK).json({
|
|
815
|
+
status_code: ErrorCodes.SUCCESS,
|
|
816
|
+
data: {
|
|
817
|
+
capabilities: capabilities.map((c) => ({
|
|
818
|
+
id: c.id,
|
|
819
|
+
name: c.name,
|
|
820
|
+
pluginID: c.pluginKey,
|
|
821
|
+
pluginVersion: c.pluginVersion
|
|
822
|
+
}))
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
} catch (error) {
|
|
826
|
+
this.logger.error("Failed to list capabilities", error);
|
|
827
|
+
res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
|
|
828
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
829
|
+
error_msg: `Failed to list capabilities: ${error instanceof Error ? error.message : String(error)}`
|
|
830
|
+
});
|
|
831
|
+
}
|
|
601
832
|
}
|
|
602
833
|
/**
|
|
603
834
|
* 获取 capability 配置
|
|
@@ -609,11 +840,7 @@ var DebugController = class _DebugController {
|
|
|
609
840
|
}
|
|
610
841
|
const config = this.capabilityService.getCapability(capabilityId);
|
|
611
842
|
if (!config) {
|
|
612
|
-
throw new
|
|
613
|
-
code: 1,
|
|
614
|
-
message: `Capability not found: ${capabilityId}`,
|
|
615
|
-
error: "CAPABILITY_NOT_FOUND"
|
|
616
|
-
}, HttpStatus.NOT_FOUND);
|
|
843
|
+
throw new CapabilityNotFoundError(capabilityId);
|
|
617
844
|
}
|
|
618
845
|
return config;
|
|
619
846
|
}
|
|
@@ -628,25 +855,21 @@ var DebugController = class _DebugController {
|
|
|
628
855
|
const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginKey);
|
|
629
856
|
const actions = pluginInstance.listActions();
|
|
630
857
|
if (actions.length === 0) {
|
|
631
|
-
throw new
|
|
632
|
-
code: 1,
|
|
633
|
-
message: `Plugin ${pluginKey} has no actions`,
|
|
634
|
-
error: "NO_ACTIONS"
|
|
635
|
-
}, HttpStatus.BAD_REQUEST);
|
|
858
|
+
throw new Error(`Plugin ${pluginKey} has no actions`);
|
|
636
859
|
}
|
|
637
860
|
return actions[0];
|
|
638
861
|
}
|
|
639
|
-
async debug(capabilityId, body) {
|
|
862
|
+
async debug(capabilityId, body, res) {
|
|
640
863
|
const startTime = Date.now();
|
|
641
864
|
const params = body.params ?? {};
|
|
642
|
-
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
643
|
-
const action = await this.getActionName(config.pluginKey, body.action);
|
|
644
|
-
const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
|
|
645
865
|
try {
|
|
866
|
+
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
867
|
+
const action = await this.getActionName(config.pluginKey, body.action);
|
|
868
|
+
const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
|
|
646
869
|
const result = await this.capabilityService.loadWithConfig(config).call(action, params, {
|
|
647
870
|
isDebug: true
|
|
648
871
|
});
|
|
649
|
-
|
|
872
|
+
res.status(HttpStatus.OK).json({
|
|
650
873
|
status_code: ErrorCodes.SUCCESS,
|
|
651
874
|
data: {
|
|
652
875
|
output: result,
|
|
@@ -658,32 +881,39 @@ var DebugController = class _DebugController {
|
|
|
658
881
|
action
|
|
659
882
|
}
|
|
660
883
|
}
|
|
661
|
-
};
|
|
884
|
+
});
|
|
662
885
|
} catch (error) {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
666
|
-
error_msg: `Capability not found: ${capabilityId}`
|
|
667
|
-
}, HttpStatus.NOT_FOUND);
|
|
668
|
-
}
|
|
669
|
-
if (error instanceof PluginNotFoundError) {
|
|
670
|
-
throw new HttpException({
|
|
671
|
-
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
672
|
-
error_msg: `Plugin not found: ${config.pluginKey}`
|
|
673
|
-
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
674
|
-
}
|
|
675
|
-
if (error instanceof ActionNotFoundError) {
|
|
676
|
-
throw new HttpException({
|
|
677
|
-
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
678
|
-
error_msg: `Action '${action}' not found in plugin ${config.pluginKey}`
|
|
679
|
-
}, HttpStatus.BAD_REQUEST);
|
|
680
|
-
}
|
|
681
|
-
throw new HttpException({
|
|
682
|
-
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
683
|
-
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
684
|
-
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
886
|
+
this.logger.error("Debug execution failed", error);
|
|
887
|
+
res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(this.buildErrorResponse(error));
|
|
685
888
|
}
|
|
686
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* 构建错误响应
|
|
892
|
+
*/
|
|
893
|
+
buildErrorResponse(error) {
|
|
894
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
895
|
+
return {
|
|
896
|
+
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
897
|
+
error_msg: `Capability not found: ${error.capabilityId}`
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
if (error instanceof PluginNotFoundError) {
|
|
901
|
+
return {
|
|
902
|
+
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
903
|
+
error_msg: `Plugin not found, please install plugin: ${error.pluginKey}`
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
if (error instanceof ActionNotFoundError) {
|
|
907
|
+
return {
|
|
908
|
+
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
909
|
+
error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
return {
|
|
913
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
914
|
+
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
915
|
+
};
|
|
916
|
+
}
|
|
687
917
|
async debugStream(capabilityId, body, res) {
|
|
688
918
|
const params = body.params ?? {};
|
|
689
919
|
res.setHeader("Content-Type", "text/event-stream");
|
|
@@ -714,9 +944,7 @@ var DebugController = class _DebugController {
|
|
|
714
944
|
status_code: ErrorCodes.SUCCESS,
|
|
715
945
|
data: {
|
|
716
946
|
type: "content",
|
|
717
|
-
delta:
|
|
718
|
-
content: pendingChunk
|
|
719
|
-
}
|
|
947
|
+
delta: pendingChunk
|
|
720
948
|
}
|
|
721
949
|
};
|
|
722
950
|
res.write(`data: ${JSON.stringify(response)}
|
|
@@ -732,9 +960,7 @@ var DebugController = class _DebugController {
|
|
|
732
960
|
status_code: ErrorCodes.SUCCESS,
|
|
733
961
|
data: {
|
|
734
962
|
type: "content",
|
|
735
|
-
delta:
|
|
736
|
-
content: pendingChunk
|
|
737
|
-
},
|
|
963
|
+
delta: pendingChunk,
|
|
738
964
|
finished: true
|
|
739
965
|
}
|
|
740
966
|
};
|
|
@@ -774,9 +1000,7 @@ var DebugController = class _DebugController {
|
|
|
774
1000
|
status_code: ErrorCodes.SUCCESS,
|
|
775
1001
|
data: {
|
|
776
1002
|
type: "content",
|
|
777
|
-
delta:
|
|
778
|
-
content: pendingChunk
|
|
779
|
-
},
|
|
1003
|
+
delta: pendingChunk,
|
|
780
1004
|
finished: true
|
|
781
1005
|
}
|
|
782
1006
|
};
|
|
@@ -806,18 +1030,23 @@ var DebugController = class _DebugController {
|
|
|
806
1030
|
};
|
|
807
1031
|
_ts_decorate4([
|
|
808
1032
|
Get("list"),
|
|
1033
|
+
_ts_param2(0, Res()),
|
|
809
1034
|
_ts_metadata2("design:type", Function),
|
|
810
|
-
_ts_metadata2("design:paramtypes", [
|
|
811
|
-
|
|
1035
|
+
_ts_metadata2("design:paramtypes", [
|
|
1036
|
+
typeof Response === "undefined" ? Object : Response
|
|
1037
|
+
]),
|
|
1038
|
+
_ts_metadata2("design:returntype", void 0)
|
|
812
1039
|
], DebugController.prototype, "list", null);
|
|
813
1040
|
_ts_decorate4([
|
|
814
1041
|
Post("debug/:capability_id"),
|
|
815
1042
|
_ts_param2(0, Param("capability_id")),
|
|
816
1043
|
_ts_param2(1, Body()),
|
|
1044
|
+
_ts_param2(2, Res()),
|
|
817
1045
|
_ts_metadata2("design:type", Function),
|
|
818
1046
|
_ts_metadata2("design:paramtypes", [
|
|
819
1047
|
String,
|
|
820
|
-
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody
|
|
1048
|
+
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody,
|
|
1049
|
+
typeof Response === "undefined" ? Object : Response
|
|
821
1050
|
]),
|
|
822
1051
|
_ts_metadata2("design:returntype", Promise)
|
|
823
1052
|
], DebugController.prototype, "debug", null);
|
|
@@ -835,6 +1064,7 @@ _ts_decorate4([
|
|
|
835
1064
|
_ts_metadata2("design:returntype", Promise)
|
|
836
1065
|
], DebugController.prototype, "debugStream", null);
|
|
837
1066
|
DebugController = _ts_decorate4([
|
|
1067
|
+
ApiExcludeController(),
|
|
838
1068
|
Controller("__innerapi__/capability"),
|
|
839
1069
|
_ts_metadata2("design:type", Function),
|
|
840
1070
|
_ts_metadata2("design:paramtypes", [
|
|
@@ -845,7 +1075,8 @@ DebugController = _ts_decorate4([
|
|
|
845
1075
|
], DebugController);
|
|
846
1076
|
|
|
847
1077
|
// src/controllers/webhook.controller.ts
|
|
848
|
-
import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2,
|
|
1078
|
+
import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpStatus as HttpStatus2, Logger as Logger4 } from "@nestjs/common";
|
|
1079
|
+
import { ApiExcludeController as ApiExcludeController2 } from "@nestjs/swagger";
|
|
849
1080
|
function _ts_decorate5(decorators, target, key, desc) {
|
|
850
1081
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
851
1082
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -872,54 +1103,69 @@ var WebhookController = class _WebhookController {
|
|
|
872
1103
|
constructor(capabilityService) {
|
|
873
1104
|
this.capabilityService = capabilityService;
|
|
874
1105
|
}
|
|
875
|
-
list() {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1106
|
+
list(res) {
|
|
1107
|
+
try {
|
|
1108
|
+
const capabilities = this.capabilityService.listCapabilities();
|
|
1109
|
+
res.status(HttpStatus2.OK).json({
|
|
1110
|
+
status_code: ErrorCodes.SUCCESS,
|
|
1111
|
+
data: {
|
|
1112
|
+
capabilities: capabilities.map((c) => ({
|
|
1113
|
+
id: c.id,
|
|
1114
|
+
name: c.name,
|
|
1115
|
+
pluginID: c.pluginKey,
|
|
1116
|
+
pluginVersion: c.pluginVersion
|
|
1117
|
+
}))
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
this.logger.error("Failed to list capabilities", error);
|
|
1122
|
+
res.status(HttpStatus2.INTERNAL_SERVER_ERROR).json({
|
|
1123
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
1124
|
+
error_msg: `Failed to list capabilities: ${error instanceof Error ? error.message : String(error)}`
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
888
1127
|
}
|
|
889
|
-
async execute(capabilityId, body) {
|
|
1128
|
+
async execute(capabilityId, body, res) {
|
|
890
1129
|
try {
|
|
891
1130
|
const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
|
|
892
|
-
|
|
1131
|
+
res.status(HttpStatus2.OK).json({
|
|
893
1132
|
status_code: ErrorCodes.SUCCESS,
|
|
894
1133
|
data: {
|
|
895
1134
|
output: result
|
|
896
1135
|
}
|
|
897
|
-
};
|
|
1136
|
+
});
|
|
898
1137
|
} catch (error) {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
902
|
-
error_msg: `Capability not found: ${capabilityId}`
|
|
903
|
-
}, HttpStatus2.NOT_FOUND);
|
|
904
|
-
}
|
|
905
|
-
if (error instanceof PluginNotFoundError) {
|
|
906
|
-
throw new HttpException2({
|
|
907
|
-
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
908
|
-
error_msg: `Plugin not found`
|
|
909
|
-
}, HttpStatus2.INTERNAL_SERVER_ERROR);
|
|
910
|
-
}
|
|
911
|
-
if (error instanceof ActionNotFoundError) {
|
|
912
|
-
throw new HttpException2({
|
|
913
|
-
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
914
|
-
error_msg: `Action '${body.action}' not found`
|
|
915
|
-
}, HttpStatus2.BAD_REQUEST);
|
|
916
|
-
}
|
|
917
|
-
throw new HttpException2({
|
|
918
|
-
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
919
|
-
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
920
|
-
}, HttpStatus2.INTERNAL_SERVER_ERROR);
|
|
1138
|
+
this.logger.error("Capability execution failed", error);
|
|
1139
|
+
res.status(HttpStatus2.INTERNAL_SERVER_ERROR).json(this.buildErrorResponse(error));
|
|
921
1140
|
}
|
|
922
1141
|
}
|
|
1142
|
+
/**
|
|
1143
|
+
* 构建错误响应
|
|
1144
|
+
*/
|
|
1145
|
+
buildErrorResponse(error) {
|
|
1146
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
1147
|
+
return {
|
|
1148
|
+
status_code: ErrorCodes.CAPABILITY_NOT_FOUND,
|
|
1149
|
+
error_msg: `Capability not found: ${error.capabilityId}`
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
if (error instanceof PluginNotFoundError) {
|
|
1153
|
+
return {
|
|
1154
|
+
status_code: ErrorCodes.PLUGIN_NOT_FOUND,
|
|
1155
|
+
error_msg: `Plugin not found, please install plugin: ${error.pluginKey}`
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
if (error instanceof ActionNotFoundError) {
|
|
1159
|
+
return {
|
|
1160
|
+
status_code: ErrorCodes.ACTION_NOT_FOUND,
|
|
1161
|
+
error_msg: `Action '${error.actionName}' not found in plugin ${error.pluginKey}`
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
return {
|
|
1165
|
+
status_code: ErrorCodes.EXECUTION_ERROR,
|
|
1166
|
+
error_msg: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
923
1169
|
async executeStream(capabilityId, body, res) {
|
|
924
1170
|
const loggerContext = {
|
|
925
1171
|
capability_id: capabilityId,
|
|
@@ -944,9 +1190,7 @@ var WebhookController = class _WebhookController {
|
|
|
944
1190
|
status_code: ErrorCodes.SUCCESS,
|
|
945
1191
|
data: {
|
|
946
1192
|
type: "content",
|
|
947
|
-
delta:
|
|
948
|
-
content: pendingChunk
|
|
949
|
-
}
|
|
1193
|
+
delta: pendingChunk
|
|
950
1194
|
}
|
|
951
1195
|
};
|
|
952
1196
|
res.write(`data: ${JSON.stringify(response)}
|
|
@@ -962,9 +1206,7 @@ var WebhookController = class _WebhookController {
|
|
|
962
1206
|
status_code: ErrorCodes.SUCCESS,
|
|
963
1207
|
data: {
|
|
964
1208
|
type: "content",
|
|
965
|
-
delta:
|
|
966
|
-
content: pendingChunk
|
|
967
|
-
},
|
|
1209
|
+
delta: pendingChunk,
|
|
968
1210
|
finished: true
|
|
969
1211
|
}
|
|
970
1212
|
};
|
|
@@ -1004,9 +1246,7 @@ var WebhookController = class _WebhookController {
|
|
|
1004
1246
|
status_code: ErrorCodes.SUCCESS,
|
|
1005
1247
|
data: {
|
|
1006
1248
|
type: "content",
|
|
1007
|
-
delta:
|
|
1008
|
-
content: pendingChunk
|
|
1009
|
-
},
|
|
1249
|
+
delta: pendingChunk,
|
|
1010
1250
|
finished: true
|
|
1011
1251
|
}
|
|
1012
1252
|
};
|
|
@@ -1036,18 +1276,23 @@ var WebhookController = class _WebhookController {
|
|
|
1036
1276
|
};
|
|
1037
1277
|
_ts_decorate5([
|
|
1038
1278
|
Get2("list"),
|
|
1279
|
+
_ts_param3(0, Res2()),
|
|
1039
1280
|
_ts_metadata3("design:type", Function),
|
|
1040
|
-
_ts_metadata3("design:paramtypes", [
|
|
1041
|
-
|
|
1281
|
+
_ts_metadata3("design:paramtypes", [
|
|
1282
|
+
typeof Response === "undefined" ? Object : Response
|
|
1283
|
+
]),
|
|
1284
|
+
_ts_metadata3("design:returntype", void 0)
|
|
1042
1285
|
], WebhookController.prototype, "list", null);
|
|
1043
1286
|
_ts_decorate5([
|
|
1044
1287
|
Post2(":capability_id"),
|
|
1045
1288
|
_ts_param3(0, Param2("capability_id")),
|
|
1046
1289
|
_ts_param3(1, Body2()),
|
|
1290
|
+
_ts_param3(2, Res2()),
|
|
1047
1291
|
_ts_metadata3("design:type", Function),
|
|
1048
1292
|
_ts_metadata3("design:paramtypes", [
|
|
1049
1293
|
String,
|
|
1050
|
-
typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody
|
|
1294
|
+
typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody,
|
|
1295
|
+
typeof Response === "undefined" ? Object : Response
|
|
1051
1296
|
]),
|
|
1052
1297
|
_ts_metadata3("design:returntype", Promise)
|
|
1053
1298
|
], WebhookController.prototype, "execute", null);
|
|
@@ -1065,6 +1310,7 @@ _ts_decorate5([
|
|
|
1065
1310
|
_ts_metadata3("design:returntype", Promise)
|
|
1066
1311
|
], WebhookController.prototype, "executeStream", null);
|
|
1067
1312
|
WebhookController = _ts_decorate5([
|
|
1313
|
+
ApiExcludeController2(),
|
|
1068
1314
|
Controller2("api/capability"),
|
|
1069
1315
|
_ts_metadata3("design:type", Function),
|
|
1070
1316
|
_ts_metadata3("design:paramtypes", [
|
|
@@ -1114,8 +1360,8 @@ var CapabilityModule = class _CapabilityModule {
|
|
|
1114
1360
|
provide: CapabilityService,
|
|
1115
1361
|
useFactory: /* @__PURE__ */ __name((requestContextService, httpClient, pluginLoader, templateEngine, moduleOptions) => {
|
|
1116
1362
|
const service = new CapabilityService(requestContextService, httpClient, pluginLoader, templateEngine);
|
|
1117
|
-
if (moduleOptions
|
|
1118
|
-
service.
|
|
1363
|
+
if (moduleOptions) {
|
|
1364
|
+
service.setOptions(moduleOptions);
|
|
1119
1365
|
}
|
|
1120
1366
|
return service;
|
|
1121
1367
|
}, "useFactory"),
|
|
@@ -1163,6 +1409,7 @@ export {
|
|
|
1163
1409
|
PluginLoaderService,
|
|
1164
1410
|
PluginNotFoundError,
|
|
1165
1411
|
TemplateEngineService,
|
|
1166
|
-
WebhookController
|
|
1412
|
+
WebhookController,
|
|
1413
|
+
migrationAdaptor
|
|
1167
1414
|
};
|
|
1168
1415
|
//# sourceMappingURL=index.js.map
|