@lark-apaas/nestjs-capability 0.0.1-alpha.6 → 0.0.1-alpha.7

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 CHANGED
@@ -217,6 +217,28 @@ var import_common3 = require("@nestjs/common");
217
217
  var import_nestjs_common = require("@lark-apaas/nestjs-common");
218
218
  var fs = __toESM(require("fs"), 1);
219
219
  var path = __toESM(require("path"), 1);
220
+
221
+ // src/utils/log-utils.ts
222
+ var DEFAULT_MAX_LENGTH = 1e3;
223
+ function truncateString(str, maxLength) {
224
+ if (str.length <= maxLength) {
225
+ return str;
226
+ }
227
+ return str.slice(0, maxLength) + `... [truncated, total ${str.length} chars]`;
228
+ }
229
+ __name(truncateString, "truncateString");
230
+ function stringifyForLog(value, maxLength = DEFAULT_MAX_LENGTH) {
231
+ try {
232
+ const str = JSON.stringify(value, null, 2);
233
+ return truncateString(str, maxLength);
234
+ } catch {
235
+ const str = String(value);
236
+ return truncateString(str, maxLength);
237
+ }
238
+ }
239
+ __name(stringifyForLog, "stringifyForLog");
240
+
241
+ // src/services/capability.service.ts
220
242
  function _ts_decorate3(decorators, target, key, desc) {
221
243
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
222
244
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -257,15 +279,15 @@ var CapabilityService = class _CapabilityService {
257
279
  __name(this, "CapabilityService");
258
280
  }
259
281
  requestContextService;
260
- httpClient;
282
+ platformHttpClient;
261
283
  pluginLoaderService;
262
284
  templateEngineService;
263
285
  logger = new import_common3.Logger(_CapabilityService.name);
264
286
  capabilities = /* @__PURE__ */ new Map();
265
287
  capabilitiesDir;
266
- constructor(requestContextService, httpClient, pluginLoaderService, templateEngineService) {
288
+ constructor(requestContextService, platformHttpClient, pluginLoaderService, templateEngineService) {
267
289
  this.requestContextService = requestContextService;
268
- this.httpClient = httpClient;
290
+ this.platformHttpClient = platformHttpClient;
269
291
  this.pluginLoaderService = pluginLoaderService;
270
292
  this.templateEngineService = templateEngineService;
271
293
  this.capabilitiesDir = path.join(process.cwd(), "server/capabilities");
@@ -353,20 +375,23 @@ var CapabilityService = class _CapabilityService {
353
375
  */
354
376
  async executeCall(config, actionName, input, contextOverride) {
355
377
  const startTime = Date.now();
378
+ const loggerContext = {
379
+ capability_id: config.id,
380
+ plugin_key: config.pluginKey,
381
+ action: actionName
382
+ };
356
383
  try {
357
384
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
358
385
  if (!pluginInstance.hasAction(actionName)) {
359
386
  throw new ActionNotFoundError(config.pluginKey, actionName);
360
387
  }
361
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
388
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
362
389
  const context = this.buildActionContext(contextOverride);
363
390
  const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
364
- this.logger.log({
365
- message: "Executing capability",
366
- capabilityId: config.id,
367
- action: actionName,
368
- pluginKey: config.pluginKey,
369
- isStream
391
+ this.logger.log("Executing capability (call)", {
392
+ ...loggerContext,
393
+ is_stream: isStream,
394
+ input: stringifyForLog(input)
370
395
  });
371
396
  let result;
372
397
  if (isStream && pluginInstance.runStream) {
@@ -378,20 +403,17 @@ var CapabilityService = class _CapabilityService {
378
403
  } else {
379
404
  result = await pluginInstance.run(actionName, context, resolvedParams);
380
405
  }
381
- this.logger.log({
382
- message: "Capability executed successfully",
383
- capabilityId: config.id,
384
- action: actionName,
385
- duration: Date.now() - startTime
406
+ this.logger.log("Capability (call) executed successfully", {
407
+ ...loggerContext,
408
+ duration_ms: Date.now() - startTime,
409
+ output: stringifyForLog(result)
386
410
  });
387
411
  return result;
388
412
  } catch (error) {
389
- this.logger.error({
390
- message: "Capability execution failed",
391
- capabilityId: config.id,
392
- action: actionName,
393
- error: error instanceof Error ? error.message : String(error),
394
- duration: Date.now() - startTime
413
+ this.logger.error("Capability (call) execution failed", {
414
+ ...loggerContext,
415
+ duration_ms: Date.now() - startTime,
416
+ error: error instanceof Error ? error.message : String(error)
395
417
  });
396
418
  throw error;
397
419
  }
@@ -403,40 +425,46 @@ var CapabilityService = class _CapabilityService {
403
425
  */
404
426
  async *executeCallStream(config, actionName, input, contextOverride) {
405
427
  const startTime = Date.now();
428
+ const loggerContext = {
429
+ capability_id: config.id,
430
+ plugin_key: config.pluginKey,
431
+ action: actionName
432
+ };
433
+ const chunks = [];
406
434
  try {
407
435
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
408
436
  if (!pluginInstance.hasAction(actionName)) {
409
437
  throw new ActionNotFoundError(config.pluginKey, actionName);
410
438
  }
411
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
439
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
412
440
  const context = this.buildActionContext(contextOverride);
413
441
  const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
414
- this.logger.log({
415
- message: "Executing capability (stream)",
416
- capabilityId: config.id,
417
- action: actionName,
418
- pluginKey: config.pluginKey,
419
- isStream
442
+ this.logger.log("Executing capability (stream)", {
443
+ ...loggerContext,
444
+ is_stream: isStream,
445
+ input: stringifyForLog(input)
420
446
  });
421
447
  if (isStream && pluginInstance.runStream) {
422
- yield* pluginInstance.runStream(actionName, context, resolvedParams);
448
+ for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
449
+ chunks.push(chunk);
450
+ yield chunk;
451
+ }
423
452
  } else {
424
453
  const result = await pluginInstance.run(actionName, context, resolvedParams);
454
+ chunks.push(result);
425
455
  yield result;
426
456
  }
427
- this.logger.log({
428
- message: "Capability stream completed",
429
- capabilityId: config.id,
430
- action: actionName,
431
- duration: Date.now() - startTime
457
+ const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
458
+ this.logger.log("Capability (stream) executed successfully", {
459
+ ...loggerContext,
460
+ duration_ms: Date.now() - startTime,
461
+ output: stringifyForLog(aggregatedResult)
432
462
  });
433
463
  } catch (error) {
434
- this.logger.error({
435
- message: "Capability stream execution failed",
436
- capabilityId: config.id,
437
- action: actionName,
438
- error: error instanceof Error ? error.message : String(error),
439
- duration: Date.now() - startTime
464
+ this.logger.error("Capability (stream) execution failed", {
465
+ ...loggerContext,
466
+ duration_ms: Date.now() - startTime,
467
+ error: error instanceof Error ? error.message : String(error)
440
468
  });
441
469
  throw error;
442
470
  }
@@ -448,27 +476,36 @@ var CapabilityService = class _CapabilityService {
448
476
  */
449
477
  async *executeCallStreamWithEvents(config, actionName, input, contextOverride) {
450
478
  const startTime = Date.now();
451
- let chunkCount = 0;
479
+ const loggerContext = {
480
+ capability_id: config.id,
481
+ plugin_key: config.pluginKey,
482
+ action: actionName
483
+ };
484
+ const chunks = [];
452
485
  try {
453
486
  const pluginInstance = await this.pluginLoaderService.loadPlugin(config.pluginKey);
454
487
  if (!pluginInstance.hasAction(actionName)) {
455
488
  throw new ActionNotFoundError(config.pluginKey, actionName);
456
489
  }
457
- const resolvedParams = this.templateEngineService.resolve(config.formValue, input);
490
+ const resolvedParams = config.formValue ? this.templateEngineService.resolve(config.formValue, input) : input;
458
491
  const context = this.buildActionContext(contextOverride);
459
- this.logger.log({
460
- message: "Executing capability (streamWithEvents)",
461
- capabilityId: config.id,
462
- action: actionName,
463
- pluginKey: config.pluginKey
492
+ const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
493
+ this.logger.log("Executing capability (streamWithEvents)", {
494
+ ...loggerContext,
495
+ is_stream: isStream,
496
+ input: stringifyForLog(input)
464
497
  });
465
498
  if (pluginInstance.runStreamWithEvents) {
466
- yield* pluginInstance.runStreamWithEvents(actionName, context, resolvedParams);
499
+ for await (const event of pluginInstance.runStreamWithEvents(actionName, context, resolvedParams)) {
500
+ if (event.type === "data") {
501
+ chunks.push(event.data);
502
+ }
503
+ yield event;
504
+ }
467
505
  } else {
468
- const isStream = pluginInstance.isStreamAction?.(actionName) ?? false;
469
506
  if (isStream && pluginInstance.runStream) {
470
507
  for await (const chunk of pluginInstance.runStream(actionName, context, resolvedParams)) {
471
- chunkCount++;
508
+ chunks.push(chunk);
472
509
  yield {
473
510
  type: "data",
474
511
  data: chunk
@@ -476,7 +513,7 @@ var CapabilityService = class _CapabilityService {
476
513
  }
477
514
  } else {
478
515
  const result = await pluginInstance.run(actionName, context, resolvedParams);
479
- chunkCount = 1;
516
+ chunks.push(result);
480
517
  yield {
481
518
  type: "data",
482
519
  data: result
@@ -485,25 +522,22 @@ var CapabilityService = class _CapabilityService {
485
522
  yield {
486
523
  type: "done",
487
524
  metadata: {
488
- chunks: chunkCount,
525
+ chunks: chunks.length,
489
526
  duration: Date.now() - startTime
490
527
  }
491
528
  };
492
529
  }
493
- this.logger.log({
494
- message: "Capability streamWithEvents completed",
495
- capabilityId: config.id,
496
- action: actionName,
497
- duration: Date.now() - startTime,
498
- chunks: chunkCount
530
+ const aggregatedResult = pluginInstance.aggregate ? pluginInstance.aggregate(actionName, chunks) : chunks;
531
+ this.logger.log("Capability (streamWithEvents) executed successfully", {
532
+ ...loggerContext,
533
+ duration_ms: Date.now() - startTime,
534
+ output: stringifyForLog(aggregatedResult)
499
535
  });
500
536
  } catch (error) {
501
- this.logger.error({
502
- message: "Capability streamWithEvents execution failed",
503
- capabilityId: config.id,
504
- action: actionName,
505
- error: error instanceof Error ? error.message : String(error),
506
- duration: Date.now() - startTime
537
+ this.logger.error("Capability (streamWithEvents) execution failed", {
538
+ ...loggerContext,
539
+ duration_ms: Date.now() - startTime,
540
+ error: error instanceof Error ? error.message : String(error)
507
541
  });
508
542
  yield {
509
543
  type: "error",
@@ -517,13 +551,14 @@ var CapabilityService = class _CapabilityService {
517
551
  buildActionContext(override) {
518
552
  return {
519
553
  logger: this.logger,
520
- httpClient: this.httpClient,
554
+ platformHttpClient: this.platformHttpClient,
521
555
  userContext: override?.userContext ?? this.getUserContext()
522
556
  };
523
557
  }
524
558
  getUserContext() {
525
559
  const ctx = this.requestContextService.getContext();
526
560
  return {
561
+ appId: ctx?.appId ?? "",
527
562
  userId: ctx?.userId ?? "",
528
563
  tenantId: ctx?.tenantId ?? ""
529
564
  };
@@ -560,13 +595,14 @@ function _ts_param2(paramIndex, decorator) {
560
595
  };
561
596
  }
562
597
  __name(_ts_param2, "_ts_param");
563
- var DebugController = class {
598
+ var DebugController = class _DebugController {
564
599
  static {
565
600
  __name(this, "DebugController");
566
601
  }
567
602
  capabilityService;
568
603
  pluginLoaderService;
569
604
  templateEngineService;
605
+ logger = new import_common4.Logger(_DebugController.name);
570
606
  constructor(capabilityService, pluginLoaderService, templateEngineService) {
571
607
  this.capabilityService = capabilityService;
572
608
  this.pluginLoaderService = pluginLoaderService;
@@ -671,45 +707,61 @@ var DebugController = class {
671
707
  }
672
708
  async debugStream(capabilityId, body, res) {
673
709
  const params = body.params ?? {};
710
+ const startTime = Date.now();
674
711
  res.setHeader("Content-Type", "text/event-stream");
675
712
  res.setHeader("Cache-Control", "no-cache");
676
713
  res.setHeader("Connection", "keep-alive");
677
714
  try {
678
715
  const config = this.getCapabilityConfig(capabilityId, body.capability);
679
716
  const action = await this.getActionName(config.pluginKey, body.action);
717
+ const loggerContext = {
718
+ capability_id: config.id,
719
+ plugin_key: config.pluginKey,
720
+ action
721
+ };
722
+ this.logger.log(`Executing capability (stream), input: ${stringifyForLog(params)}`, loggerContext);
680
723
  const capability = this.capabilityService.loadWithConfig(config);
681
724
  const eventStream = capability.callStreamWithEvents(action, params);
725
+ let pendingChunk = null;
726
+ const allChunks = [];
682
727
  for await (const event of eventStream) {
683
728
  switch (event.type) {
684
729
  case "data": {
685
- const response = {
686
- status_code: ErrorCodes.SUCCESS,
687
- data: {
688
- type: "content",
689
- delta: {
690
- content: event.data
730
+ allChunks.push(event.data);
731
+ if (pendingChunk !== null) {
732
+ const response = {
733
+ status_code: ErrorCodes.SUCCESS,
734
+ data: {
735
+ type: "content",
736
+ delta: {
737
+ content: pendingChunk
738
+ }
691
739
  }
692
- }
693
- };
694
- res.write(`data: ${JSON.stringify(response)}
740
+ };
741
+ res.write(`data: ${JSON.stringify(response)}
695
742
 
696
743
  `);
744
+ }
745
+ pendingChunk = event.data;
697
746
  break;
698
747
  }
699
748
  case "done": {
700
- const response = {
701
- status_code: ErrorCodes.SUCCESS,
702
- data: {
703
- type: "content",
704
- delta: {
705
- content: null
706
- },
707
- finished: true
708
- }
709
- };
710
- res.write(`data: ${JSON.stringify(response)}
749
+ if (pendingChunk !== null) {
750
+ const response = {
751
+ status_code: ErrorCodes.SUCCESS,
752
+ data: {
753
+ type: "content",
754
+ delta: {
755
+ content: pendingChunk
756
+ },
757
+ finished: true
758
+ }
759
+ };
760
+ res.write(`data: ${JSON.stringify(response)}
711
761
 
712
762
  `);
763
+ }
764
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
713
765
  res.end();
714
766
  return;
715
767
  }
@@ -732,6 +784,21 @@ var DebugController = class {
732
784
  }
733
785
  }
734
786
  }
787
+ if (pendingChunk !== null) {
788
+ const response = {
789
+ status_code: ErrorCodes.SUCCESS,
790
+ data: {
791
+ type: "content",
792
+ delta: {
793
+ content: pendingChunk
794
+ },
795
+ finished: true
796
+ }
797
+ };
798
+ res.write(`data: ${JSON.stringify(response)}
799
+
800
+ `);
801
+ }
735
802
  res.end();
736
803
  } catch (error) {
737
804
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -811,11 +878,12 @@ function _ts_param3(paramIndex, decorator) {
811
878
  };
812
879
  }
813
880
  __name(_ts_param3, "_ts_param");
814
- var WebhookController = class {
881
+ var WebhookController = class _WebhookController {
815
882
  static {
816
883
  __name(this, "WebhookController");
817
884
  }
818
885
  capabilityService;
886
+ logger = new import_common5.Logger(_WebhookController.name);
819
887
  constructor(capabilityService) {
820
888
  this.capabilityService = capabilityService;
821
889
  }
@@ -868,43 +936,58 @@ var WebhookController = class {
868
936
  }
869
937
  }
870
938
  async executeStream(capabilityId, body, res) {
939
+ const startTime = Date.now();
940
+ const loggerContext = {
941
+ capability_id: capabilityId,
942
+ action: body.action
943
+ };
871
944
  res.setHeader("Content-Type", "text/event-stream");
872
945
  res.setHeader("Cache-Control", "no-cache");
873
946
  res.setHeader("Connection", "keep-alive");
874
947
  try {
948
+ this.logger.log(`Executing capability (stream), input: ${stringifyForLog(body.params)}`, loggerContext);
875
949
  const capability = this.capabilityService.load(capabilityId);
876
950
  const eventStream = capability.callStreamWithEvents(body.action, body.params);
951
+ let pendingChunk = null;
952
+ const allChunks = [];
877
953
  for await (const event of eventStream) {
878
954
  switch (event.type) {
879
955
  case "data": {
880
- const response = {
881
- status_code: ErrorCodes.SUCCESS,
882
- data: {
883
- type: "content",
884
- delta: {
885
- content: event.data
956
+ allChunks.push(event.data);
957
+ if (pendingChunk !== null) {
958
+ const response = {
959
+ status_code: ErrorCodes.SUCCESS,
960
+ data: {
961
+ type: "content",
962
+ delta: {
963
+ content: pendingChunk
964
+ }
886
965
  }
887
- }
888
- };
889
- res.write(`data: ${JSON.stringify(response)}
966
+ };
967
+ res.write(`data: ${JSON.stringify(response)}
890
968
 
891
969
  `);
970
+ }
971
+ pendingChunk = event.data;
892
972
  break;
893
973
  }
894
974
  case "done": {
895
- const response = {
896
- status_code: ErrorCodes.SUCCESS,
897
- data: {
898
- type: "content",
899
- delta: {
900
- content: null
901
- },
902
- finished: true
903
- }
904
- };
905
- res.write(`data: ${JSON.stringify(response)}
975
+ if (pendingChunk !== null) {
976
+ const response = {
977
+ status_code: ErrorCodes.SUCCESS,
978
+ data: {
979
+ type: "content",
980
+ delta: {
981
+ content: pendingChunk
982
+ },
983
+ finished: true
984
+ }
985
+ };
986
+ res.write(`data: ${JSON.stringify(response)}
906
987
 
907
988
  `);
989
+ }
990
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
908
991
  res.end();
909
992
  return;
910
993
  }
@@ -927,6 +1010,22 @@ var WebhookController = class {
927
1010
  }
928
1011
  }
929
1012
  }
1013
+ if (pendingChunk !== null) {
1014
+ const response = {
1015
+ status_code: ErrorCodes.SUCCESS,
1016
+ data: {
1017
+ type: "content",
1018
+ delta: {
1019
+ content: pendingChunk
1020
+ },
1021
+ finished: true
1022
+ }
1023
+ };
1024
+ res.write(`data: ${JSON.stringify(response)}
1025
+
1026
+ `);
1027
+ }
1028
+ this.logger.log(`Capability (stream) executed successfully, duration: ${Date.now() - startTime}ms, chunks: ${allChunks.length}, result: ${stringifyForLog(allChunks)}`, loggerContext);
930
1029
  res.end();
931
1030
  } catch (error) {
932
1031
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -1014,6 +1113,9 @@ var CapabilityModule = class _CapabilityModule {
1014
1113
  static forRoot(options) {
1015
1114
  return {
1016
1115
  module: _CapabilityModule,
1116
+ imports: [
1117
+ import_nestjs_common2.CommonModule
1118
+ ],
1017
1119
  controllers: getControllers(),
1018
1120
  providers: [
1019
1121
  {
@@ -1048,6 +1150,9 @@ var CapabilityModule = class _CapabilityModule {
1048
1150
  };
1049
1151
  CapabilityModule = _ts_decorate6([
1050
1152
  (0, import_common6.Module)({
1153
+ imports: [
1154
+ import_nestjs_common2.CommonModule
1155
+ ],
1051
1156
  controllers: getControllers(),
1052
1157
  providers: [
1053
1158
  CapabilityService,