@lark-apaas/nestjs-capability 0.0.1-alpha.0 → 0.0.1-alpha.2
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/README.md +107 -5
- package/dist/index.cjs +261 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -9
- package/dist/index.d.ts +86 -9
- package/dist/index.js +263 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -97,7 +97,7 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
97
97
|
}
|
|
98
98
|
logger = new Logger(_PluginLoaderService.name);
|
|
99
99
|
pluginInstances = /* @__PURE__ */ new Map();
|
|
100
|
-
loadPlugin(pluginID) {
|
|
100
|
+
async loadPlugin(pluginID) {
|
|
101
101
|
const cached = this.pluginInstances.get(pluginID);
|
|
102
102
|
if (cached) {
|
|
103
103
|
this.logger.debug(`Using cached plugin instance: ${pluginID}`);
|
|
@@ -105,7 +105,7 @@ var PluginLoaderService = class _PluginLoaderService {
|
|
|
105
105
|
}
|
|
106
106
|
this.logger.log(`Loading plugin: ${pluginID}`);
|
|
107
107
|
try {
|
|
108
|
-
const pluginPackage =
|
|
108
|
+
const pluginPackage = (await import(pluginID)).default;
|
|
109
109
|
if (typeof pluginPackage.create !== "function") {
|
|
110
110
|
throw new PluginLoadError(pluginID, "Plugin does not export create() function");
|
|
111
111
|
}
|
|
@@ -241,28 +241,70 @@ var CapabilityService = class _CapabilityService {
|
|
|
241
241
|
if (!config) {
|
|
242
242
|
throw new CapabilityNotFoundError(capabilityId);
|
|
243
243
|
}
|
|
244
|
+
return this.createExecutor(config);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 使用传入的配置加载能力执行器
|
|
248
|
+
* 用于 debug 场景,支持用户传入自定义配置
|
|
249
|
+
*/
|
|
250
|
+
loadWithConfig(config) {
|
|
251
|
+
return this.createExecutor(config);
|
|
252
|
+
}
|
|
253
|
+
createExecutor(config) {
|
|
244
254
|
return {
|
|
245
255
|
call: /* @__PURE__ */ __name(async (actionName, input, contextOverride) => {
|
|
246
|
-
return this.
|
|
247
|
-
}, "call")
|
|
256
|
+
return this.executeCall(config, actionName, input, contextOverride);
|
|
257
|
+
}, "call"),
|
|
258
|
+
callStream: /* @__PURE__ */ __name((actionName, input, contextOverride) => {
|
|
259
|
+
return this.executeCallStream(config, actionName, input, contextOverride);
|
|
260
|
+
}, "callStream"),
|
|
261
|
+
isStream: /* @__PURE__ */ __name(async (actionName) => {
|
|
262
|
+
return this.checkIsStream(config, actionName);
|
|
263
|
+
}, "isStream")
|
|
248
264
|
};
|
|
249
265
|
}
|
|
250
|
-
|
|
266
|
+
/**
|
|
267
|
+
* 检查 action 是否为流式
|
|
268
|
+
*/
|
|
269
|
+
async checkIsStream(config, actionName) {
|
|
270
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
271
|
+
if (!pluginInstance.hasAction(actionName)) {
|
|
272
|
+
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
273
|
+
}
|
|
274
|
+
return pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* 执行 capability(始终返回 Promise)
|
|
278
|
+
* - unary action: 直接返回结果
|
|
279
|
+
* - stream action: 内部聚合所有 chunk 后返回
|
|
280
|
+
*/
|
|
281
|
+
async executeCall(config, actionName, input, contextOverride) {
|
|
251
282
|
const startTime = Date.now();
|
|
252
283
|
try {
|
|
253
|
-
const pluginInstance = this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
284
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
254
285
|
if (!pluginInstance.hasAction(actionName)) {
|
|
255
286
|
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
256
287
|
}
|
|
257
288
|
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
258
289
|
const context = this.buildActionContext(contextOverride);
|
|
290
|
+
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
259
291
|
this.logger.log({
|
|
260
292
|
message: "Executing capability",
|
|
261
293
|
capabilityId: config.id,
|
|
262
294
|
action: actionName,
|
|
263
|
-
pluginID: config.pluginID
|
|
295
|
+
pluginID: config.pluginID,
|
|
296
|
+
isStream
|
|
264
297
|
});
|
|
265
|
-
|
|
298
|
+
let result;
|
|
299
|
+
if (isStream && pluginInstance.runStream) {
|
|
300
|
+
const chunks = [];
|
|
301
|
+
for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
|
|
302
|
+
chunks.push(chunk);
|
|
303
|
+
}
|
|
304
|
+
result = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
|
|
305
|
+
} else {
|
|
306
|
+
result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
307
|
+
}
|
|
266
308
|
this.logger.log({
|
|
267
309
|
message: "Capability executed successfully",
|
|
268
310
|
capabilityId: config.id,
|
|
@@ -281,6 +323,51 @@ var CapabilityService = class _CapabilityService {
|
|
|
281
323
|
throw error;
|
|
282
324
|
}
|
|
283
325
|
}
|
|
326
|
+
/**
|
|
327
|
+
* 流式执行 capability
|
|
328
|
+
* - stream action: 返回原始 AsyncIterable
|
|
329
|
+
* - unary action: 包装为单次 yield
|
|
330
|
+
*/
|
|
331
|
+
async *executeCallStream(config, actionName, input, contextOverride) {
|
|
332
|
+
const startTime = Date.now();
|
|
333
|
+
try {
|
|
334
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);
|
|
335
|
+
if (!pluginInstance.hasAction(actionName)) {
|
|
336
|
+
throw new ActionNotFoundError(config.pluginID, actionName);
|
|
337
|
+
}
|
|
338
|
+
const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
|
|
339
|
+
const context = this.buildActionContext(contextOverride);
|
|
340
|
+
const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
|
|
341
|
+
this.logger.log({
|
|
342
|
+
message: "Executing capability (stream)",
|
|
343
|
+
capabilityId: config.id,
|
|
344
|
+
action: actionName,
|
|
345
|
+
pluginID: config.pluginID,
|
|
346
|
+
isStream
|
|
347
|
+
});
|
|
348
|
+
if (isStream && pluginInstance.runStream) {
|
|
349
|
+
yield* pluginInstance.runStream(actionName, context, resolvedParams);
|
|
350
|
+
} else {
|
|
351
|
+
const result = await pluginInstance.run(actionName, context, resolvedParams);
|
|
352
|
+
yield result;
|
|
353
|
+
}
|
|
354
|
+
this.logger.log({
|
|
355
|
+
message: "Capability stream completed",
|
|
356
|
+
capabilityId: config.id,
|
|
357
|
+
action: actionName,
|
|
358
|
+
duration: Date.now() - startTime
|
|
359
|
+
});
|
|
360
|
+
} catch (error) {
|
|
361
|
+
this.logger.error({
|
|
362
|
+
message: "Capability stream execution failed",
|
|
363
|
+
capabilityId: config.id,
|
|
364
|
+
action: actionName,
|
|
365
|
+
error: error instanceof Error ? error.message : String(error),
|
|
366
|
+
duration: Date.now() - startTime
|
|
367
|
+
});
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
284
371
|
buildActionContext(override) {
|
|
285
372
|
return {
|
|
286
373
|
logger: this.logger,
|
|
@@ -309,7 +396,7 @@ CapabilityService = _ts_decorate3([
|
|
|
309
396
|
], CapabilityService);
|
|
310
397
|
|
|
311
398
|
// src/controllers/debug.controller.ts
|
|
312
|
-
import { Controller, Post, Get, Param, Body, HttpException, HttpStatus } from "@nestjs/common";
|
|
399
|
+
import { Controller, Post, Get, Param, Body, Res, HttpException, HttpStatus } from "@nestjs/common";
|
|
313
400
|
function _ts_decorate4(decorators, target, key, desc) {
|
|
314
401
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
315
402
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -332,9 +419,11 @@ var DebugController = class {
|
|
|
332
419
|
__name(this, "DebugController");
|
|
333
420
|
}
|
|
334
421
|
capabilityService;
|
|
422
|
+
pluginLoaderService;
|
|
335
423
|
templateEngineService;
|
|
336
|
-
constructor(capabilityService, templateEngineService) {
|
|
424
|
+
constructor(capabilityService, pluginLoaderService, templateEngineService) {
|
|
337
425
|
this.capabilityService = capabilityService;
|
|
426
|
+
this.pluginLoaderService = pluginLoaderService;
|
|
338
427
|
this.templateEngineService = templateEngineService;
|
|
339
428
|
}
|
|
340
429
|
list() {
|
|
@@ -350,8 +439,14 @@ var DebugController = class {
|
|
|
350
439
|
}))
|
|
351
440
|
};
|
|
352
441
|
}
|
|
353
|
-
|
|
354
|
-
|
|
442
|
+
/**
|
|
443
|
+
* 获取 capability 配置
|
|
444
|
+
* 优先使用 body.capability,否则从服务获取
|
|
445
|
+
*/
|
|
446
|
+
getCapabilityConfig(capabilityId, bodyCapability) {
|
|
447
|
+
if (bodyCapability) {
|
|
448
|
+
return bodyCapability;
|
|
449
|
+
}
|
|
355
450
|
const config = this.capabilityService.getCapability(capabilityId);
|
|
356
451
|
if (!config) {
|
|
357
452
|
throw new HttpException({
|
|
@@ -360,9 +455,35 @@ var DebugController = class {
|
|
|
360
455
|
error: "CAPABILITY_NOT_FOUND"
|
|
361
456
|
}, HttpStatus.NOT_FOUND);
|
|
362
457
|
}
|
|
363
|
-
|
|
458
|
+
return config;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* 获取 action 名称
|
|
462
|
+
* 优先使用传入的 action,否则使用插件第一个 action
|
|
463
|
+
*/
|
|
464
|
+
async getActionName(pluginID, bodyAction) {
|
|
465
|
+
if (bodyAction) {
|
|
466
|
+
return bodyAction;
|
|
467
|
+
}
|
|
468
|
+
const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);
|
|
469
|
+
const actions = pluginInstance.listActions();
|
|
470
|
+
if (actions.length === 0) {
|
|
471
|
+
throw new HttpException({
|
|
472
|
+
code: 1,
|
|
473
|
+
message: `Plugin ${pluginID} has no actions`,
|
|
474
|
+
error: "NO_ACTIONS"
|
|
475
|
+
}, HttpStatus.BAD_REQUEST);
|
|
476
|
+
}
|
|
477
|
+
return actions[0];
|
|
478
|
+
}
|
|
479
|
+
async debug(capabilityId, body) {
|
|
480
|
+
const startTime = Date.now();
|
|
481
|
+
const params = body.params ?? {};
|
|
482
|
+
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
483
|
+
const action = await this.getActionName(config.pluginID, body.action);
|
|
484
|
+
const resolvedParams = this.templateEngineService.resolve(config.formValue, params);
|
|
364
485
|
try {
|
|
365
|
-
const result = await this.capabilityService.
|
|
486
|
+
const result = await this.capabilityService.loadWithConfig(config).call(action, params);
|
|
366
487
|
return {
|
|
367
488
|
code: 0,
|
|
368
489
|
message: "success",
|
|
@@ -371,7 +492,8 @@ var DebugController = class {
|
|
|
371
492
|
capabilityConfig: config,
|
|
372
493
|
resolvedParams,
|
|
373
494
|
duration: Date.now() - startTime,
|
|
374
|
-
pluginID: config.pluginID
|
|
495
|
+
pluginID: config.pluginID,
|
|
496
|
+
action
|
|
375
497
|
}
|
|
376
498
|
};
|
|
377
499
|
} catch (error) {
|
|
@@ -393,7 +515,8 @@ var DebugController = class {
|
|
|
393
515
|
error: "PLUGIN_NOT_FOUND",
|
|
394
516
|
debug: {
|
|
395
517
|
duration,
|
|
396
|
-
pluginID: config.pluginID
|
|
518
|
+
pluginID: config.pluginID,
|
|
519
|
+
action
|
|
397
520
|
}
|
|
398
521
|
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
399
522
|
}
|
|
@@ -404,7 +527,8 @@ var DebugController = class {
|
|
|
404
527
|
error: "ACTION_NOT_FOUND",
|
|
405
528
|
debug: {
|
|
406
529
|
duration,
|
|
407
|
-
pluginID: config.pluginID
|
|
530
|
+
pluginID: config.pluginID,
|
|
531
|
+
action
|
|
408
532
|
}
|
|
409
533
|
}, HttpStatus.BAD_REQUEST);
|
|
410
534
|
}
|
|
@@ -415,11 +539,51 @@ var DebugController = class {
|
|
|
415
539
|
debug: {
|
|
416
540
|
duration,
|
|
417
541
|
pluginID: config.pluginID,
|
|
542
|
+
action,
|
|
418
543
|
resolvedParams
|
|
419
544
|
}
|
|
420
545
|
}, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
421
546
|
}
|
|
422
547
|
}
|
|
548
|
+
async debugStream(capabilityId, body, res) {
|
|
549
|
+
const params = body.params ?? {};
|
|
550
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
551
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
552
|
+
res.setHeader("Connection", "keep-alive");
|
|
553
|
+
try {
|
|
554
|
+
const config = this.getCapabilityConfig(capabilityId, body.capability);
|
|
555
|
+
const action = await this.getActionName(config.pluginID, body.action);
|
|
556
|
+
const capability = this.capabilityService.loadWithConfig(config);
|
|
557
|
+
const stream = capability.callStream(action, params);
|
|
558
|
+
for await (const chunk of stream) {
|
|
559
|
+
res.write(`data: ${JSON.stringify(chunk)}
|
|
560
|
+
|
|
561
|
+
`);
|
|
562
|
+
}
|
|
563
|
+
res.write("data: [DONE]\n\n");
|
|
564
|
+
} catch (error) {
|
|
565
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
566
|
+
let errorCode = "EXECUTION_ERROR";
|
|
567
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
568
|
+
errorCode = "CAPABILITY_NOT_FOUND";
|
|
569
|
+
} else if (error instanceof PluginNotFoundError) {
|
|
570
|
+
errorCode = "PLUGIN_NOT_FOUND";
|
|
571
|
+
} else if (error instanceof ActionNotFoundError) {
|
|
572
|
+
errorCode = "ACTION_NOT_FOUND";
|
|
573
|
+
} else if (error instanceof HttpException) {
|
|
574
|
+
const response = error.getResponse();
|
|
575
|
+
errorCode = response.error ?? "EXECUTION_ERROR";
|
|
576
|
+
}
|
|
577
|
+
res.write(`data: ${JSON.stringify({
|
|
578
|
+
error: message,
|
|
579
|
+
code: errorCode
|
|
580
|
+
})}
|
|
581
|
+
|
|
582
|
+
`);
|
|
583
|
+
} finally {
|
|
584
|
+
res.end();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
423
587
|
};
|
|
424
588
|
_ts_decorate4([
|
|
425
589
|
Get("list"),
|
|
@@ -434,21 +598,35 @@ _ts_decorate4([
|
|
|
434
598
|
_ts_metadata2("design:type", Function),
|
|
435
599
|
_ts_metadata2("design:paramtypes", [
|
|
436
600
|
String,
|
|
437
|
-
typeof
|
|
601
|
+
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody
|
|
438
602
|
]),
|
|
439
603
|
_ts_metadata2("design:returntype", Promise)
|
|
440
604
|
], DebugController.prototype, "debug", null);
|
|
605
|
+
_ts_decorate4([
|
|
606
|
+
Post("debug/:capability_id/stream"),
|
|
607
|
+
_ts_param2(0, Param("capability_id")),
|
|
608
|
+
_ts_param2(1, Body()),
|
|
609
|
+
_ts_param2(2, Res()),
|
|
610
|
+
_ts_metadata2("design:type", Function),
|
|
611
|
+
_ts_metadata2("design:paramtypes", [
|
|
612
|
+
String,
|
|
613
|
+
typeof DebugRequestBody === "undefined" ? Object : DebugRequestBody,
|
|
614
|
+
typeof Response === "undefined" ? Object : Response
|
|
615
|
+
]),
|
|
616
|
+
_ts_metadata2("design:returntype", Promise)
|
|
617
|
+
], DebugController.prototype, "debugStream", null);
|
|
441
618
|
DebugController = _ts_decorate4([
|
|
442
619
|
Controller("__innerapi__/capability"),
|
|
443
620
|
_ts_metadata2("design:type", Function),
|
|
444
621
|
_ts_metadata2("design:paramtypes", [
|
|
445
622
|
typeof CapabilityService === "undefined" ? Object : CapabilityService,
|
|
623
|
+
typeof PluginLoaderService === "undefined" ? Object : PluginLoaderService,
|
|
446
624
|
typeof TemplateEngineService === "undefined" ? Object : TemplateEngineService
|
|
447
625
|
])
|
|
448
626
|
], DebugController);
|
|
449
627
|
|
|
450
628
|
// src/controllers/webhook.controller.ts
|
|
451
|
-
import { Controller as Controller2, Post as Post2, Param as Param2, Body as Body2, HttpException as HttpException2, HttpStatus as HttpStatus2 } from "@nestjs/common";
|
|
629
|
+
import { Controller as Controller2, Get as Get2, Post as Post2, Param as Param2, Body as Body2, Res as Res2, HttpException as HttpException2, HttpStatus as HttpStatus2 } from "@nestjs/common";
|
|
452
630
|
function _ts_decorate5(decorators, target, key, desc) {
|
|
453
631
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
454
632
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -474,6 +652,20 @@ var WebhookController = class {
|
|
|
474
652
|
constructor(capabilityService) {
|
|
475
653
|
this.capabilityService = capabilityService;
|
|
476
654
|
}
|
|
655
|
+
list() {
|
|
656
|
+
const capabilities = this.capabilityService.listCapabilities();
|
|
657
|
+
return {
|
|
658
|
+
code: 0,
|
|
659
|
+
message: "success",
|
|
660
|
+
data: capabilities.map((c) => ({
|
|
661
|
+
id: c.id,
|
|
662
|
+
name: c.name,
|
|
663
|
+
description: c.description,
|
|
664
|
+
pluginID: c.pluginID,
|
|
665
|
+
pluginVersion: c.pluginVersion
|
|
666
|
+
}))
|
|
667
|
+
};
|
|
668
|
+
}
|
|
477
669
|
async execute(capabilityId, body) {
|
|
478
670
|
try {
|
|
479
671
|
const result = await this.capabilityService.load(capabilityId).call(body.action, body.params);
|
|
@@ -511,7 +703,46 @@ var WebhookController = class {
|
|
|
511
703
|
}, HttpStatus2.INTERNAL_SERVER_ERROR);
|
|
512
704
|
}
|
|
513
705
|
}
|
|
706
|
+
async executeStream(capabilityId, body, res) {
|
|
707
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
708
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
709
|
+
res.setHeader("Connection", "keep-alive");
|
|
710
|
+
try {
|
|
711
|
+
const capability = this.capabilityService.load(capabilityId);
|
|
712
|
+
const stream = capability.callStream(body.action, body.params);
|
|
713
|
+
for await (const chunk of stream) {
|
|
714
|
+
res.write(`data: ${JSON.stringify(chunk)}
|
|
715
|
+
|
|
716
|
+
`);
|
|
717
|
+
}
|
|
718
|
+
res.write("data: [DONE]\n\n");
|
|
719
|
+
} catch (error) {
|
|
720
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
721
|
+
let errorCode = "EXECUTION_ERROR";
|
|
722
|
+
if (error instanceof CapabilityNotFoundError) {
|
|
723
|
+
errorCode = "CAPABILITY_NOT_FOUND";
|
|
724
|
+
} else if (error instanceof PluginNotFoundError) {
|
|
725
|
+
errorCode = "PLUGIN_NOT_FOUND";
|
|
726
|
+
} else if (error instanceof ActionNotFoundError) {
|
|
727
|
+
errorCode = "ACTION_NOT_FOUND";
|
|
728
|
+
}
|
|
729
|
+
res.write(`data: ${JSON.stringify({
|
|
730
|
+
error: message,
|
|
731
|
+
code: errorCode
|
|
732
|
+
})}
|
|
733
|
+
|
|
734
|
+
`);
|
|
735
|
+
} finally {
|
|
736
|
+
res.end();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
514
739
|
};
|
|
740
|
+
_ts_decorate5([
|
|
741
|
+
Get2("list"),
|
|
742
|
+
_ts_metadata3("design:type", Function),
|
|
743
|
+
_ts_metadata3("design:paramtypes", []),
|
|
744
|
+
_ts_metadata3("design:returntype", typeof ListResponse === "undefined" ? Object : ListResponse)
|
|
745
|
+
], WebhookController.prototype, "list", null);
|
|
515
746
|
_ts_decorate5([
|
|
516
747
|
Post2(":capability_id"),
|
|
517
748
|
_ts_param3(0, Param2("capability_id")),
|
|
@@ -523,6 +754,19 @@ _ts_decorate5([
|
|
|
523
754
|
]),
|
|
524
755
|
_ts_metadata3("design:returntype", Promise)
|
|
525
756
|
], WebhookController.prototype, "execute", null);
|
|
757
|
+
_ts_decorate5([
|
|
758
|
+
Post2(":capability_id/stream"),
|
|
759
|
+
_ts_param3(0, Param2("capability_id")),
|
|
760
|
+
_ts_param3(1, Body2()),
|
|
761
|
+
_ts_param3(2, Res2()),
|
|
762
|
+
_ts_metadata3("design:type", Function),
|
|
763
|
+
_ts_metadata3("design:paramtypes", [
|
|
764
|
+
String,
|
|
765
|
+
typeof ExecuteRequestBody === "undefined" ? Object : ExecuteRequestBody,
|
|
766
|
+
typeof Response === "undefined" ? Object : Response
|
|
767
|
+
]),
|
|
768
|
+
_ts_metadata3("design:returntype", Promise)
|
|
769
|
+
], WebhookController.prototype, "executeStream", null);
|
|
526
770
|
WebhookController = _ts_decorate5([
|
|
527
771
|
Controller2("api/capability"),
|
|
528
772
|
_ts_metadata3("design:type", Function),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class TemplateEngineService {\n private readonly TEMPLATE_REGEX = /^\\{\\{input\\.(.+)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n const match = template.match(this.TEMPLATE_REGEX);\n if (!match) {\n return template;\n }\n\n const path = match[1];\n return this.getValueByPath(input, path);\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginID: string) {\n super(`Plugin not found: ${pluginID}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginID: string, reason: string) {\n super(`Failed to load plugin ${pluginID}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n loadPlugin(pluginID: string): PluginInstance {\n const cached = this.pluginInstances.get(pluginID);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginID}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginID}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = require(pluginID) as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginID, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginID, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginID}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginID);\n }\n throw new PluginLoadError(\n pluginID,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginID: string): boolean {\n try {\n require.resolve(pluginID);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginID?: string): void {\n if (pluginID) {\n this.pluginInstances.delete(pluginID);\n this.logger.log(`Cleared cache for plugin: ${pluginID}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginID: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginID}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.execute(config, actionName, input, contextOverride);\n },\n };\n }\n\n private async execute(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n });\n\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginID: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginID: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n body.params,\n );\n\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginID: config.pluginID,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginID: config.pluginID,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n}\n","import {\n Controller,\n Post,\n Param,\n Body,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["Injectable","TemplateEngineService","TEMPLATE_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","match","path","getValueByPath","result","key","value","Object","entries","obj","keys","split","current","undefined","Injectable","Logger","PluginNotFoundError","Error","pluginID","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","require","create","instance","set","error","code","message","String","isPluginInstalled","resolve","clearCache","delete","clear","Injectable","Logger","Inject","RequestContextService","PLATFORM_HTTP_CLIENT","fs","path","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginID","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","call","input","contextOverride","execute","startTime","Date","now","pluginInstance","loadPlugin","hasAction","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","Controller","Post","Get","Param","Body","HttpException","HttpStatus","DebugController","capabilityService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginID","pluginVersion","debug","capabilityId","body","startTime","Date","now","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","resolvedParams","resolve","formValue","params","result","load","call","action","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","Controller","Post","Param","Body","HttpException","HttpStatus","WebhookController","capabilityService","execute","capabilityId","body","result","load","call","action","params","code","message","data","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","Module","RequestContextService","PLATFORM_HTTP_CLIENT","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
|
|
1
|
+
{"version":3,"sources":["../src/services/template-engine.service.ts","../src/services/plugin-loader.service.ts","../src/services/capability.service.ts","../src/controllers/debug.controller.ts","../src/controllers/webhook.controller.ts","../src/capability.module.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class TemplateEngineService {\n private readonly TEMPLATE_REGEX = /^\\{\\{input\\.(.+)\\}\\}$/;\n\n resolve(template: unknown, input: Record<string, unknown>): unknown {\n if (typeof template === 'string') {\n return this.resolveString(template, input);\n }\n\n if (Array.isArray(template)) {\n return template.map(item => this.resolve(item, input));\n }\n\n if (template !== null && typeof template === 'object') {\n return this.resolveObject(template as Record<string, unknown>, input);\n }\n\n return template;\n }\n\n private resolveString(template: string, input: Record<string, unknown>): unknown {\n const match = template.match(this.TEMPLATE_REGEX);\n if (!match) {\n return template;\n }\n\n const path = match[1];\n return this.getValueByPath(input, path);\n }\n\n private resolveObject(\n template: Record<string, unknown>,\n input: Record<string, unknown>,\n ): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(template)) {\n result[key] = this.resolve(value, input);\n }\n\n return result;\n }\n\n private getValueByPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n }\n}\n","import { Injectable, Logger } from '@nestjs/common';\nimport type { PluginInstance, PluginPackage } from '../interfaces';\n\nexport class PluginNotFoundError extends Error {\n constructor(pluginID: string) {\n super(`Plugin not found: ${pluginID}`);\n this.name = 'PluginNotFoundError';\n }\n}\n\nexport class PluginLoadError extends Error {\n constructor(pluginID: string, reason: string) {\n super(`Failed to load plugin ${pluginID}: ${reason}`);\n this.name = 'PluginLoadError';\n }\n}\n\n@Injectable()\nexport class PluginLoaderService {\n private readonly logger = new Logger(PluginLoaderService.name);\n private readonly pluginInstances = new Map<string, PluginInstance>();\n\n async loadPlugin(pluginID: string): Promise<PluginInstance> {\n const cached = this.pluginInstances.get(pluginID);\n if (cached) {\n this.logger.debug(`Using cached plugin instance: ${pluginID}`);\n return cached;\n }\n\n this.logger.log(`Loading plugin: ${pluginID}`);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pluginPackage = (await import(pluginID)).default as PluginPackage;\n\n if (typeof pluginPackage.create !== 'function') {\n throw new PluginLoadError(pluginID, 'Plugin does not export create() function');\n }\n\n const instance = pluginPackage.create();\n this.pluginInstances.set(pluginID, instance);\n\n this.logger.log(`Plugin loaded successfully: ${pluginID}`);\n return instance;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n throw new PluginNotFoundError(pluginID);\n }\n throw new PluginLoadError(\n pluginID,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n\n isPluginInstalled(pluginID: string): boolean {\n try {\n require.resolve(pluginID);\n return true;\n } catch {\n return false;\n }\n }\n\n clearCache(pluginID?: string): void {\n if (pluginID) {\n this.pluginInstances.delete(pluginID);\n this.logger.log(`Cleared cache for plugin: ${pluginID}`);\n } else {\n this.pluginInstances.clear();\n this.logger.log('Cleared all plugin caches');\n }\n }\n}\n","import { Injectable, Logger, Inject, OnModuleInit } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n type PlatformHttpClient,\n} from '@lark-apaas/nestjs-common';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { CapabilityConfig, PluginActionContext, UserContext } from '../interfaces';\nimport { PluginLoaderService } from './plugin-loader.service';\nimport { TemplateEngineService } from './template-engine.service';\n\nexport class CapabilityNotFoundError extends Error {\n constructor(capabilityId: string) {\n super(`Capability not found: ${capabilityId}`);\n this.name = 'CapabilityNotFoundError';\n }\n}\n\nexport class ActionNotFoundError extends Error {\n constructor(pluginID: string, actionName: string) {\n super(`Action '${actionName}' not found in plugin ${pluginID}`);\n this.name = 'ActionNotFoundError';\n }\n}\n\nexport interface CapabilityExecutor {\n /**\n * 调用 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n call(actionName: string, input: unknown, context?: Partial<PluginActionContext>): Promise<unknown>;\n\n /**\n * 流式调用 capability\n * - 返回原始 AsyncIterable\n * - 如果 action 是 unary,包装为单次 yield\n */\n callStream(actionName: string, input: unknown, context?: Partial<PluginActionContext>): AsyncIterable<unknown>;\n\n /**\n * 检查 action 是否为流式\n */\n isStream(actionName: string): Promise<boolean>;\n}\n\nexport interface CapabilityModuleOptions {\n capabilitiesDir?: string;\n}\n\n@Injectable()\nexport class CapabilityService implements OnModuleInit {\n private readonly logger = new Logger(CapabilityService.name);\n private readonly capabilities = new Map<string, CapabilityConfig>();\n private capabilitiesDir: string;\n\n constructor(\n private readonly requestContextService: RequestContextService,\n @Inject(PLATFORM_HTTP_CLIENT) private readonly httpClient: PlatformHttpClient,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {\n this.capabilitiesDir = path.join(process.cwd(), 'server/capabilities');\n }\n\n setCapabilitiesDir(dir: string): void {\n this.capabilitiesDir = dir;\n }\n\n async onModuleInit(): Promise<void> {\n await this.loadCapabilities();\n }\n\n private async loadCapabilities(): Promise<void> {\n this.logger.log(`Loading capabilities from ${this.capabilitiesDir}`);\n\n if (!fs.existsSync(this.capabilitiesDir)) {\n this.logger.warn(`Capabilities directory not found: ${this.capabilitiesDir}`);\n return;\n }\n\n const files = fs.readdirSync(this.capabilitiesDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = path.join(this.capabilitiesDir, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n const config = JSON.parse(content) as CapabilityConfig;\n\n if (!config.id) {\n this.logger.warn(`Skipping capability without id: ${file}`);\n continue;\n }\n\n this.capabilities.set(config.id, config);\n this.logger.log(`Loaded capability: ${config.id} (${config.name})`);\n } catch (error) {\n this.logger.error(`Failed to load capability from ${file}:`, error);\n }\n }\n\n this.logger.log(`Loaded ${this.capabilities.size} capabilities`);\n }\n\n listCapabilities(): CapabilityConfig[] {\n return Array.from(this.capabilities.values());\n }\n\n getCapability(capabilityId: string): CapabilityConfig | null {\n return this.capabilities.get(capabilityId) ?? null;\n }\n\n load(capabilityId: string): CapabilityExecutor {\n const config = this.capabilities.get(capabilityId);\n if (!config) {\n throw new CapabilityNotFoundError(capabilityId);\n }\n\n return this.createExecutor(config);\n }\n\n /**\n * 使用传入的配置加载能力执行器\n * 用于 debug 场景,支持用户传入自定义配置\n */\n loadWithConfig(config: CapabilityConfig): CapabilityExecutor {\n return this.createExecutor(config);\n }\n\n private createExecutor(config: CapabilityConfig): CapabilityExecutor {\n return {\n call: async (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCall(config, actionName, input, contextOverride);\n },\n\n callStream: (\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ) => {\n return this.executeCallStream(config, actionName, input, contextOverride);\n },\n\n isStream: async (actionName: string) => {\n return this.checkIsStream(config, actionName);\n },\n };\n }\n\n /**\n * 检查 action 是否为流式\n */\n private async checkIsStream(config: CapabilityConfig, actionName: string): Promise<boolean> {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n return pluginInstance.isStreamAction?.(actionName) ?? false;\n }\n\n /**\n * 执行 capability(始终返回 Promise)\n * - unary action: 直接返回结果\n * - stream action: 内部聚合所有 chunk 后返回\n */\n private async executeCall(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): Promise<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n let result: unknown;\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:聚合所有 chunk\n const chunks: unknown[] = [];\n for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {\n chunks.push(chunk);\n }\n // 使用插件的聚合方法,或默认返回 chunks 数组\n result = pluginInstance.aggregate\n ? pluginInstance.aggregate(actionName, chunks)\n : chunks;\n } else {\n // 非流式 action:直接调用\n result = await pluginInstance.run(actionName, context, resolvedParams);\n }\n\n this.logger.log({\n message: 'Capability executed successfully',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n\n return result;\n } catch (error) {\n this.logger.error({\n message: 'Capability execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n /**\n * 流式执行 capability\n * - stream action: 返回原始 AsyncIterable\n * - unary action: 包装为单次 yield\n */\n private async *executeCallStream(\n config: CapabilityConfig,\n actionName: string,\n input: unknown,\n contextOverride?: Partial<PluginActionContext>,\n ): AsyncIterable<unknown> {\n const startTime = Date.now();\n\n try {\n const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginID);\n\n if (!pluginInstance.hasAction(actionName)) {\n throw new ActionNotFoundError(config.pluginID, actionName);\n }\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n input as Record<string, unknown>,\n );\n\n const context = this.buildActionContext(contextOverride);\n const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;\n\n this.logger.log({\n message: 'Executing capability (stream)',\n capabilityId: config.id,\n action: actionName,\n pluginID: config.pluginID,\n isStream,\n });\n\n if (isStream && pluginInstance.runStream) {\n // 流式 action:透传 AsyncIterable\n yield* pluginInstance.runStream(actionName, context, resolvedParams);\n } else {\n // 非流式 action:包装为单次 yield\n const result = await pluginInstance.run(actionName, context, resolvedParams);\n yield result;\n }\n\n this.logger.log({\n message: 'Capability stream completed',\n capabilityId: config.id,\n action: actionName,\n duration: Date.now() - startTime,\n });\n } catch (error) {\n this.logger.error({\n message: 'Capability stream execution failed',\n capabilityId: config.id,\n action: actionName,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n private buildActionContext(override?: Partial<PluginActionContext>): PluginActionContext {\n return {\n logger: this.logger,\n httpClient: this.httpClient,\n userContext: override?.userContext ?? this.getUserContext(),\n };\n }\n\n private getUserContext(): UserContext {\n const ctx = this.requestContextService.getContext();\n return {\n userId: ctx?.userId ?? '',\n tenantId: ctx?.tenantId ?? '',\n };\n }\n}\n","import {\n Controller,\n Post,\n Get,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginLoaderService, PluginNotFoundError } from '../services/plugin-loader.service';\nimport { TemplateEngineService } from '../services/template-engine.service';\nimport type { CapabilityConfig } from '../interfaces';\n\ninterface DebugRequestBody {\n action?: string;\n params?: Record<string, unknown>;\n capability?: CapabilityConfig;\n}\n\ninterface DebugResponse {\n code: number;\n message: string;\n data: unknown;\n debug?: {\n capabilityConfig: unknown;\n resolvedParams: unknown;\n duration: number;\n pluginID: string;\n action: string;\n };\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: Array<{\n id: string;\n name: string;\n pluginID: string;\n pluginVersion: string;\n }>;\n}\n\n@Controller('__innerapi__/capability')\nexport class DebugController {\n constructor(\n private readonly capabilityService: CapabilityService,\n private readonly pluginLoaderService: PluginLoaderService,\n private readonly templateEngineService: TemplateEngineService,\n ) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n /**\n * 获取 capability 配置\n * 优先使用 body.capability,否则从服务获取\n */\n private getCapabilityConfig(\n capabilityId: string,\n bodyCapability?: CapabilityConfig,\n ): CapabilityConfig {\n if (bodyCapability) {\n return bodyCapability;\n }\n\n const config = this.capabilityService.getCapability(capabilityId);\n if (!config) {\n throw new HttpException(\n {\n code: 1,\n message: `Capability not found: ${capabilityId}`,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n return config;\n }\n\n /**\n * 获取 action 名称\n * 优先使用传入的 action,否则使用插件第一个 action\n */\n private async getActionName(pluginID: string, bodyAction?: string): Promise<string> {\n if (bodyAction) {\n return bodyAction;\n }\n\n const pluginInstance = await this.pluginLoaderService.loadPlugin(pluginID);\n const actions = pluginInstance.listActions();\n\n if (actions.length === 0) {\n throw new HttpException(\n {\n code: 1,\n message: `Plugin ${pluginID} has no actions`,\n error: 'NO_ACTIONS',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n return actions[0];\n }\n\n @Post('debug/:capability_id')\n async debug(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n ): Promise<DebugResponse> {\n const startTime = Date.now();\n const params = body.params ?? {};\n\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const resolvedParams = this.templateEngineService.resolve(\n config.formValue,\n params,\n );\n\n try {\n const result = await this.capabilityService\n .loadWithConfig(config)\n .call(action, params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n debug: {\n capabilityConfig: config,\n resolvedParams,\n duration: Date.now() - startTime,\n pluginID: config.pluginID,\n action,\n },\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n debug: { duration },\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n debug: { duration, pluginID: config.pluginID, action },\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n debug: {\n duration,\n pluginID: config.pluginID,\n action,\n resolvedParams,\n },\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post('debug/:capability_id/stream')\n async debugStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: DebugRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n const params = body.params ?? {};\n\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const config = this.getCapabilityConfig(capabilityId, body.capability);\n const action = await this.getActionName(config.pluginID, body.action);\n\n const capability = this.capabilityService.loadWithConfig(config);\n const stream = capability.callStream(action, params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n } else if (error instanceof HttpException) {\n const response = error.getResponse() as { error?: string };\n errorCode = response.error ?? 'EXECUTION_ERROR';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import {\n Controller,\n Get,\n Post,\n Param,\n Body,\n Res,\n HttpException,\n HttpStatus,\n} from '@nestjs/common';\nimport type { Response } from 'express';\nimport {\n CapabilityService,\n CapabilityNotFoundError,\n ActionNotFoundError,\n} from '../services/capability.service';\nimport { PluginNotFoundError } from '../services/plugin-loader.service';\n\ninterface ExecuteRequestBody {\n action: string;\n params: Record<string, unknown>;\n}\n\ninterface ExecuteResponse {\n code: number;\n message: string;\n data: unknown;\n}\n\ninterface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n pluginID: string;\n pluginVersion: string;\n}\n\ninterface ListResponse {\n code: number;\n message: string;\n data: CapabilityInfo[];\n}\n\n@Controller('api/capability')\nexport class WebhookController {\n constructor(private readonly capabilityService: CapabilityService) {}\n\n @Get('list')\n list(): ListResponse {\n const capabilities = this.capabilityService.listCapabilities();\n return {\n code: 0,\n message: 'success',\n data: capabilities.map(c => ({\n id: c.id,\n name: c.name,\n description: c.description,\n pluginID: c.pluginID,\n pluginVersion: c.pluginVersion,\n })),\n };\n }\n\n @Post(':capability_id')\n async execute(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n ): Promise<ExecuteResponse> {\n try {\n const result = await this.capabilityService\n .load(capabilityId)\n .call(body.action, body.params);\n\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n if (error instanceof CapabilityNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'CAPABILITY_NOT_FOUND',\n },\n HttpStatus.NOT_FOUND,\n );\n }\n\n if (error instanceof PluginNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'PLUGIN_NOT_FOUND',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n\n if (error instanceof ActionNotFoundError) {\n throw new HttpException(\n {\n code: 1,\n message: error.message,\n error: 'ACTION_NOT_FOUND',\n },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n throw new HttpException(\n {\n code: 1,\n message: error instanceof Error ? error.message : String(error),\n error: 'EXECUTION_ERROR',\n },\n HttpStatus.INTERNAL_SERVER_ERROR,\n );\n }\n }\n\n @Post(':capability_id/stream')\n async executeStream(\n @Param('capability_id') capabilityId: string,\n @Body() body: ExecuteRequestBody,\n @Res() res: Response,\n ): Promise<void> {\n // 设置 SSE 响应头\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n\n try {\n const capability = this.capabilityService.load(capabilityId);\n const stream = capability.callStream(body.action, body.params);\n\n for await (const chunk of stream) {\n res.write(`data: ${JSON.stringify(chunk)}\\n\\n`);\n }\n\n // 发送结束标记\n res.write('data: [DONE]\\n\\n');\n } catch (error) {\n // 错误时发送错误信息\n const message = error instanceof Error ? error.message : String(error);\n let errorCode = 'EXECUTION_ERROR';\n\n if (error instanceof CapabilityNotFoundError) {\n errorCode = 'CAPABILITY_NOT_FOUND';\n } else if (error instanceof PluginNotFoundError) {\n errorCode = 'PLUGIN_NOT_FOUND';\n } else if (error instanceof ActionNotFoundError) {\n errorCode = 'ACTION_NOT_FOUND';\n }\n\n res.write(`data: ${JSON.stringify({ error: message, code: errorCode })}\\n\\n`);\n } finally {\n res.end();\n }\n }\n}\n","import { Module, DynamicModule, Type } from '@nestjs/common';\nimport {\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n} from '@lark-apaas/nestjs-common';\nimport { DebugController, WebhookController } from './controllers';\nimport {\n CapabilityService,\n PluginLoaderService,\n TemplateEngineService,\n type CapabilityModuleOptions,\n} from './services';\n\nconst CAPABILITY_OPTIONS = Symbol('CAPABILITY_OPTIONS');\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\nfunction getControllers(): Type[] {\n const controllers: Type[] = [WebhookController];\n if (isDevelopment) {\n controllers.push(DebugController);\n }\n return controllers;\n}\n\n@Module({\n controllers: getControllers(),\n providers: [CapabilityService, PluginLoaderService, TemplateEngineService],\n exports: [CapabilityService],\n})\nexport class CapabilityModule {\n static forRoot(options?: CapabilityModuleOptions): DynamicModule {\n return {\n module: CapabilityModule,\n controllers: getControllers(),\n providers: [\n {\n provide: CAPABILITY_OPTIONS,\n useValue: options ?? {},\n },\n {\n provide: CapabilityService,\n useFactory: (\n requestContextService: RequestContextService,\n httpClient: any,\n pluginLoader: PluginLoaderService,\n templateEngine: TemplateEngineService,\n moduleOptions: CapabilityModuleOptions,\n ) => {\n const service = new CapabilityService(\n requestContextService,\n httpClient,\n pluginLoader,\n templateEngine,\n );\n if (moduleOptions?.capabilitiesDir) {\n service.setCapabilitiesDir(moduleOptions.capabilitiesDir);\n }\n return service;\n },\n inject: [\n RequestContextService,\n PLATFORM_HTTP_CLIENT,\n PluginLoaderService,\n TemplateEngineService,\n CAPABILITY_OPTIONS,\n ],\n },\n PluginLoaderService,\n TemplateEngineService,\n ],\n exports: [CapabilityService],\n };\n }\n}\n"],"mappings":"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","names":["Injectable","TemplateEngineService","TEMPLATE_REGEX","resolve","template","input","resolveString","Array","isArray","map","item","resolveObject","match","path","getValueByPath","result","key","value","Object","entries","obj","keys","split","current","undefined","Injectable","Logger","PluginNotFoundError","Error","pluginID","name","PluginLoadError","reason","PluginLoaderService","logger","Logger","pluginInstances","Map","loadPlugin","cached","get","debug","log","pluginPackage","default","create","instance","set","error","code","message","String","isPluginInstalled","require","resolve","clearCache","delete","clear","Injectable","Logger","Inject","RequestContextService","PLATFORM_HTTP_CLIENT","fs","path","CapabilityNotFoundError","Error","capabilityId","name","ActionNotFoundError","pluginID","actionName","CapabilityService","logger","Logger","capabilities","Map","capabilitiesDir","requestContextService","httpClient","pluginLoaderService","templateEngineService","join","process","cwd","setCapabilitiesDir","dir","onModuleInit","loadCapabilities","log","existsSync","warn","files","readdirSync","filter","f","endsWith","file","filePath","content","readFileSync","config","JSON","parse","id","set","error","size","listCapabilities","Array","from","values","getCapability","get","load","createExecutor","loadWithConfig","call","input","contextOverride","executeCall","callStream","executeCallStream","isStream","checkIsStream","pluginInstance","loadPlugin","hasAction","isStreamAction","startTime","Date","now","resolvedParams","resolve","formValue","context","buildActionContext","message","action","result","runStream","chunks","chunk","push","aggregate","run","duration","String","override","userContext","getUserContext","ctx","getContext","userId","tenantId","Controller","Post","Get","Param","Body","Res","HttpException","HttpStatus","DebugController","capabilityService","pluginLoaderService","templateEngineService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","pluginID","pluginVersion","getCapabilityConfig","capabilityId","bodyCapability","config","getCapability","HttpException","error","HttpStatus","NOT_FOUND","getActionName","bodyAction","pluginInstance","loadPlugin","actions","listActions","length","BAD_REQUEST","debug","body","startTime","Date","now","params","capability","action","resolvedParams","resolve","formValue","result","loadWithConfig","call","capabilityConfig","duration","CapabilityNotFoundError","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","Error","String","debugStream","res","setHeader","stream","callStream","chunk","write","JSON","stringify","errorCode","response","getResponse","end","Controller","Get","Post","Param","Body","Res","HttpException","HttpStatus","WebhookController","capabilityService","list","capabilities","listCapabilities","code","message","data","map","c","id","name","description","pluginID","pluginVersion","execute","capabilityId","body","result","load","call","action","params","error","CapabilityNotFoundError","HttpException","HttpStatus","NOT_FOUND","PluginNotFoundError","INTERNAL_SERVER_ERROR","ActionNotFoundError","BAD_REQUEST","Error","String","executeStream","res","setHeader","capability","stream","callStream","chunk","write","JSON","stringify","errorCode","end","Module","RequestContextService","PLATFORM_HTTP_CLIENT","CAPABILITY_OPTIONS","Symbol","isDevelopment","process","env","NODE_ENV","getControllers","controllers","WebhookController","push","DebugController","CapabilityModule","forRoot","options","module","providers","provide","useValue","CapabilityService","useFactory","requestContextService","httpClient","pluginLoader","templateEngine","moduleOptions","service","capabilitiesDir","setCapabilitiesDir","inject","RequestContextService","PLATFORM_HTTP_CLIENT","PluginLoaderService","TemplateEngineService","exports"]}
|